0% found this document useful (0 votes)
266 views

Calcul Stiintific Java

The document discusses programming numerical applications in Java, presenting ways to implement numerical methods using iterative algorithms and creating a small numerical library as an example. It explores using tools like Apache Ant for configuration and task execution, and accessing mathematical capabilities from products like Mathematica, Maple and Scilab from Java. The goal is to show how to develop scientific computing applications in Java without relying on an integrated development environment.

Uploaded by

scheiber
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
266 views

Calcul Stiintific Java

The document discusses programming numerical applications in Java, presenting ways to implement numerical methods using iterative algorithms and creating a small numerical library as an example. It explores using tools like Apache Ant for configuration and task execution, and accessing mathematical capabilities from products like Mathematica, Maple and Scilab from Java. The goal is to show how to develop scientific computing applications in Java without relying on an integrated development environment.

Uploaded by

scheiber
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 210

Ernest SCHEIBER

JAVA IN
CALCULUL S
TIINT
IFIC

Brasov
2016

Cuprins
I

Programarea aplicatiilor numerice n Java

1 Aplicatii numerice simple


1.1 Pseudocodul unui algoritm iterativ . . . . . .
1.2 Metode numerice . . . . . . . . . . . . . . . .
1.3 Probleme conexe . . . . . . . . . . . . . . . .
1.3.1 Jurnalizare . . . . . . . . . . . . . . .
1.3.2 Verificarea rezultatelor cu junit . . . .
1.3.3 Unealta de dezvoltare apache-ant . . .
1.3.4 Gestiunea proiectelor cu apache-maven
1.4 O mini-biblioteca numerica . . . . . . . . . . .
1.5 Formatarea rezultatetor . . . . . . . . . . . .
1.6 Rezolvarea problemelor . . . . . . . . . . . . .
1.7 Dezvoltarea mini-bibliotecii cu apache-maven
1.8 Utilizare prin OSGi . . . . . . . . . . . . . . .
2 Accesarea n Java a unor
2.1 Java cu Mathematica
2.2 Java cu Maple . . . . .
2.3 Java cu Scilab . . . . .

9
.
.
.
.
.
.
.
.
.
.
.
.

11
11
12
14
15
16
17
20
25
33
34
36
39

produse matematice
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

47
47
51
53

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

3 Pachete Java de calcul numeric


65
3.1 apache commons-math . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
3.2 Jama . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
4 Calcul simbolic n Java
73
4.1 Calcul simbolic prin Mathematica . . . . . . . . . . . . . . . . . . . . . . . 73
4.2 Calcul simbolic prin Maple . . . . . . . . . . . . . . . . . . . . . . . . . . 74
4.3 Symja - Java Computer Algebra Library . . . . . . . . . . . . . . . . . . . 75
5 Expresie de calcul dat
a ca String
77
5.1 Java Expression Parser - JEP . . . . . . . . . . . . . . . . . . . . . . . . . 77
5.2 MathEclipse-Parser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
3

CUPRINS

6 Aplicatii cu interfat
a grafic
a
6.1 Rezolvarea unei ecuatii algebrice . . . . . . . . .
6.1.1 Interfata grafica bazata pe JavaFX . . .
6.2 Rezolvarea unui sistem algebric de ecuatii liniare
6.2.1 Interfata grafica bazata pe Swing . . . .
7 Generarea reprezent
arilor grafice
7.1 PtPlot . . . . . . . . . . . . . . .
7.2 jfreechart . . . . . . . . . . . . .
7.3 VisAD . . . . . . . . . . . . . . .
7.4 Vizualizarea functiilor complexe .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

8 Aplicatii Web
8.1 Servlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.1.1 Codul unui servlet . . . . . . . . . . . . . . . . . . .
8.1.2 Program client al unui servlet . . . . . . . . . . . . .
8.1.3 Dezvoltarea unui servlet prin maven . . . . . . . . .
8.1.4 Servlet ca modul OSGi . . . . . . . . . . . . . . . . .
8.2 WebSocket . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.2.1 Interfata de programare HTML5 de client WebSocket
8.2.2 WebSocket n Java . . . . . . . . . . . . . . . . . . .
8.2.3 Client Java pentru WebSocket . . . . . . . . . . . . .
8.3 Google Web Toolkit (GWT) . . . . . . . . . . . . . . . . . .
8.3.1 Dezvoltarea unei aplicatii cu GWT . . . . . . . . . .
8.4 Desfasurarea n nor . . . . . . . . . . . . . . . . . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

83
83
84
86
86

.
.
.
.

.
.
.
.

91
91
95
100
108

.
.
.
.
.
.
.
.
.
.
.
.

125
. 127
. 128
. 132
. 133
. 135
. 138
. 138
. 140
. 144
. 145
. 146
. 155

.
.
.
.

9 Inc
arcarea unui fisier - upload
159
9.1 Preluarea unei matrice prin functii Javascript . . . . . . . . . . . . . . . . 159
9.2 FileUpload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
10 Servicii Web
10.1 Descrierea unui serviciu . . . . . . .
10.2 Modelul JAX-WS prin Metro . . .
10.2.1 Serviciu JAX-WS ca servlet
10.3 Modelul JAX-RS prin jersey . . . .

II

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

167
168
168
169
172

Programare paralel
a n Java

179

11 Introducere n programarea concurent


a
11.1 Procese paralele . . . . . . . . . . . . . .
11.2 Probleme specifice calculului paralel . . .
11.3 Eficienta programelor paralele . . . . . .
11.4 Programare paralela n Java . . . . . . .
11.5 Metode numerice paralele . . . . . . . .

181
. 181
. 184
. 186
. 189
. 189

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

CUPRINS

12 Algoritm paralel si iterativ


193
12.1 Algoritm paralel si iterativ asincron . . . . . . . . . . . . . . . . . . . . . . 194
13 OpenCL prin Aparapi
197
13.1 Aparapi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
13.2 Programare n aparapi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
13.3 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
Bibliografie

209

CUPRINS

Prefat
a
Lucrarea de fata are ca obiectiv problematica legata de implementarea n Java a
aplicatiilor de calcul stiintific si este o versiune actualizata a lucrarii noastre, [10].
Din partea cititorului vom presupune existenta unor abilitati de programare n Java
si binenteles, cunostinte elementare de calcul numeric. Anumite parti din lucrare cer
cititorului familiarizarea cu un anumit produs informatic. Pentru fiecare produs utilizat,
Internetul ofera o multime de informatii privind instalarea, utilizarea, exemple, interfata
de programare, raspunsuri la ntrebari frecvente, etc.
Implementarea unei metode de calcul numeric bazat pe un algoritm iterativ este exemplificata prin crearea unei mini-biblioteci de programe numerice care este folosit pe
parcursul lucrari. Pentru configurarea si executarea sarcinilor se va utiliza cu precadere
apache-ant.
Vom pune n evidenta posibilitatea utilizarii n Java a resurselor oferite de produsele
matematice Mathematica, Maple si Scilab.
Utilizarea limbajului de programare Java n calculul stiintific este reprezentata prin
biblioteci de clase pentru rezolvarea unor probleme specifice domeniului. Lucrarea exemplifica doar folosirea pachetele apache commons-math si Jama.
O evidenta si observatii comparative a resurselor de calcul stiintific se gasesc pe Internet [13, 14].
Utilizarea unei functii definita printr-un sir de caractere este o problema de programare
specifica unei aplicatii de calcul numeric care se doreste utilizata prin intermediul unei
interfete grafice sau n mediu distribuit.
Interfetele grafice si aspecte privind vizualizarea unor obiecte matematice sunt de
asemenea atinse. Este dat un exemplu de interfata grafica programata n JavaFX, pachet
dezvoltat n ultimii ani, parte din distributia Java Development Kit - JDK. Se prezinta
solutii pentru vizualizarea graficului unei functii, prin intermediul unor produse specializate, integrabile n aplicatii Java.
Tipurile de aplicatii distribuite tratate n lucrare sunt aplicatiile Web bazate pe servlet
si serviciile Web dezvoltate pe modelul apelului de procedura la distanta (Remote Procedure Call) dar si serviciile REST. Exemplificarile utilizeaza pachetele metro si respectiv,
jersey. Prin utilizarea pachetului apache commons-fileupload este data o solutie pentru
ncarcarea unui fisier.
In prezent calculatoarele uzuale permit efectuarea de calcule n paralel prin unitatea
de procesare grafica (GPU). Exemplificam tehnica de programare n Java prin produsul
Aparapi, bazat pe OpenCL.
Codurile tuturor programelor din lucrare pot fi descarcate de la adresa
7

CUPRINS

https://github.com/e-scheiber/Scientific_Computing_and_Java.git.

Partea I
Programarea aplicatiilor numerice n
Java

Capitolul 1
Aplicatii numerice simple
Scopul acestui capitol este prezentarea unui mod de implementare n limbajul de programare Java a unor metode numerice. Se vor utiliza mai multe produse informatice
ajutatoare dar nu vom face apel la un mediu integrat de dezvoltare (Integrated Development Environment - IDE). Motivatia acestei optiuni este simpla: un mediu integrat de
dezvoltare acopera (ascunde, face transparenta) multe din activitatile care se ntreprind.
In plus, din punct de vedere educativ, nu dorim sa promovam un anumit mediu integrat
de dezvoltare n dauna altuia.
Pentru nceput ne propunem sa calculam:
1. Solutia negativa a ecuatiei 2x x2 = 0.
Ecuatia are 3 solutii x1 0.7666647 (1, 12 ), x2 = 2, x3 = 4;
R
2. Integrala 04 ln(1 + tan x)dx = 8 ln 2 0.2721983;
probleme pentru care se vor realiza programe simple. Apoi aceste programe vor fi dezvoltate pentru a putea trata un caz general si pentru a putea fi utilizate n mediu distribuit.
Rezolvarea numerica a unei probleme de calcul numeric conduce de multe ori la construirea unui sir (xk )kN , despre care se arata ca converge ntr-un sens catre solutia problemei. Rezultate privind evaluarea erorii, a vitezei de convergenta, a complexitatii unui
algoritm sunt factori care prezinta importanta n alegerea metodei de rezolvare numerica
a unei probleme.
Aspectele care ne intereseaza privesc implementarea metodelor de rezolvare numerica
utilizand limbajul de programare Java.

1.1

Pseudocodul unui algoritm iterativ

Una dintre proprietatile unui algoritm este finitudinea. Pentru aceasta este nevoie de
o regula de oprire. Spre exemplificare, n cadrul unei probleme numerice, o regula de
oprire simpla este:
Daca eroarea relativa (absoluta) a aproximatiei xk+1 = Y pentru xk = X este mai
mica decat un numar pozitiv eps, sau daca numarul de iteratii executate ni este egal cu
11

12

CAPITOLUL 1. APLICAT
II NUMERICE SIMPLE

numarul maxim admis de iteratii nmi atunci programul se opreste; altfel se trece la o
noua iteratie.
Dupa oprirea calculelor, se pozitioneaza un indicator de raspuns ind pe 0, daca eroarea
relativa este mai mica decat eps, iar n caz contrar pe 1.
Numarul eps este denumit toleranta de calcul sau test de precizie.
Natura problemei poate impune si alte conditii pentru terminarea procesului de calcul
iar valoarea parametrului ind va preciza felul n care a avut loc oprirea calculului.
Pseudocodul algoritmului metodei iterative este
Algorithm 1 Pseudocodul metodei iterative

1: procedure metoda iterativa


2:
generarea aproximat
iei init
iale Y
3:
ni 0
4:
do
5:
ni ni + 1
6:
XY
7:
generarea aproximat
iei urm
atoare Y
Xk
8:
d kYkXk
9:
while (d eps) si (ni < nmi)
10:
if d < eps then
11:
ind 0
12:
else
13:
ind 1
14:
end if
15:
return Y
16: end procedure
In Java exista posibilitatea ca n locul limitarii numarului maxim admis de iteratii
sa fie fixata durata maxima admisa de timp de calcul [9]. Aceasta abordare utilizeaza
programare concurenta prin fire de executie, tematica ce nu face obiectul acestei lucrari.

1.2

Metode numerice pentru rezolvarea problemelor

Calculul solutiei negative a ecuatiei 2x x2 = 0


Determinarea solutie negative a ecuatei f (x) := 2x x2 = 0 se va face utilizand metoda
tangentei [5, 3]:
f (xk )
xk+1 = xk 0
.
(1.1)
f (xk )
Daca aproximatia initiala x0 este aleasa ntr-o vecinatate convenabila a unei solutii, atunci
sirul (1.1) converge catre aceea solutie.
Aproximatia initiala o vom alege x0 = 0.5.

13

1.2. METODE NUMERICE

Derivata f 0 (x) a functiei date de membrul stang al ecuatiei, ntr-un punct, va fi calculata numeric utilizand extrapolarea Richardson, [3]. Se construieste tabloul subdiagonal
D0,0
D1,0
..
.

D1,1
..
.

Dm,0 Dm,1

..

.
. . . Dm,m

folosind formulele de recurenta


Dk,0 =
Dk,j =

f (x +

h
)
2k

f (x

h
)
2k

h
2k

k = 0, 1 . . . , m;

4j
1
Dk,j1 j
Dk1,j1
j
4 1
4 1

j = 1, 2, . . . , m;
k = j, j + 1, . . . , m.

Aproximatia derivatei va fi Dm,m .


Datele de intrare pe care utilizatorul - clientul - trebuie sa le furnizeze sunt:
expresia lui f (x);
aproximatia initiala;
toleranta;
numarul maxim admis de iteratii.
Datele de iesire pe care le asteptam sa le primim de la programul de calcul sunt:
indicatorul de raspuns al programului;
aproximatia solutiei obtinute;
valoarea membrului stang al ecuatiei calculata n solutia aproximativa obtinuta;
numarul iteratiilor efectuate.
De multe ori prezinta interes urmarirea evolutiei rezultatelor intermediare. Accesul la
aceste date va fi o cerinta a programelor ce vor fi dezvoltate.

Calculul integralei

R
4

ln(1 + tan x)dx

Pentru calculul integralei se va utiliza o schema adaptiva bazata pe metoda lui Simpson
[11]
Z
a

m1

m1

X
X
ba
f (x)dx =
[f (a) + 2
f (a2i ) + 4
f (a2i+1 ) + f (b)]
6m
i=1
i=0

(1.2)

14

CAPITOLUL 1. APLICAT
II NUMERICE SIMPLE

(b a)5 (4)
f (),
2880m4
, i {0, 1, . . . , 2m}.
unde ai = a + i ba
2m
Practic, integrala se aproximeaza prin

m1

m1

X
X
ba
Jm =
[f (a) + 2
f (a2i ) + 4
f (a2i+1 ) + f (b)]
6m
i=1
i=0
ultimul termen din (1.2), denumit rest, se neglijeaza. Astfel apare o eroare de metoda care
se suprapune peste erorile de rotunjire datorate reprezentarii numerelor reale n virgula
mobila din memoria unui calculator si calculului aritmetic corespunzator.
Schema adaptiva consta din calculul unui sir (Jmk )k . Elementele sirului se calculeaza
pana la ndeplinirea unei conditii din regula de oprire. Sirul (mk )kN il vom defini prin
formula de recurenta mk+1 = 2mk .
In acest fel, daca notam prin S p , S i sumele
m
m
p
Sm

m1
X

f (a2i ) si

i=1

i
Sm

m1
X

f (a2i+1 )

i=0

p
i
i
p
.
. La fiecare noua iteratie va trebui calculata doar suma Sm+1
+ Sm
atunci Sm+1
= Sm

Datele de intrare pe care clientul trebuie sa le furnizeze sunt:


expresia de integrat f (x);
limitele de integrare;
toleranta;
numarul maxim admis de iteratii.
Datele de iesire pe care le asteptam sa le primim de la programul de calcul sunt:
indicatorul de raspuns al programului;
aproximatia integralei;
numarul iteratiilor efectuate.

1.3

Probleme conexe

La elaborarea si dezvoltarea programelor suntem confruntati cu problemele:


Jurnalizarea adica afisarea / retinerea rezultatelor sau evenimentelor ntr-un fisier.
Deseori prezinta interes evolutia procesului de calcul prin prisma unor rezultate intermediare. In acest sens se pot utiliza pachetele / produsele: java.util.logging
din jdk, apache-log4j (The Apache Software Foundation) - www.apache.org,
slf4j (Simple Logging Facade for Java) - www.QOS.ch, Quality of Open Software,
logback - logback.qos.ch.

1.3. PROBLEME CONEXE

15

Verificarea rezultatelor obtinute. Fiind dat rezultatul, fiecare dintre problemele propuse este o problema de test. Rolul unei probleme de test este verificarea functionarii
programului de rezolvare, depistarea unor greseli. In acest sens vom utiliza produsul
junit.
Alt produs cu acelasi scop este TestNG.
Dezvoltarea aplicatiei, n sensul simplificarii operatiilor de compilare, arhivare, rularea problemelor de test, etc. Vom arata modul de folosire pentru
apache-ant. Se presupune ca toate resursele utilizate, cuprinse uzual n fisiere
cu extensia jar (j ava ar hive) sunt disponibile pe calculatorul local. Daca
calculatorul este conectat la Internet, atunci, folosind suplimentar apache-ivy,
resursele publice pot fi descarcate mpreuna cu toate dependintele si utilizate
prin apache-ant.
apache-maven 1 este un alt cadru de dezvoltare si gestiune a proiectelor (Project
management framework). Calculatorul pe care se dezvolta proiectul / aplicatia
trebuie sa fie conectat la Internet. Resursele necesare ndeplinirii diferitelor
sarcini (maven artifacts) sunt preluate din Internet si depuse ntr-un depozit
local maven (local repository). In prezent sunt ntretinute depozite publice
de resurse soft necesare dezvoltarii de aplicatii cu maven 2 iar dezvoltatorii de
instrumente soft au posibilitatea de a-si promova produsele prin depunerea
ntr-un depozit maven. Dintr-un asemenea depozit public resursele necesare
sunt descarcate n depozitul local.

1.3.1

Jurnalizare

Jurnalizare prin java.util.logging


Sablonul de programare cu afisarea mesajelor pe ecranul monitorului este
1

import j a v a . u t i l . l o g g i n g . Logger ;

public c l a s s Exemplu{
s t a t i c Logger l o g g e r = Logger . g e t L o g g e r ( Exemplu . c l a s s . getName ( ) ) ;

public s t a t i c void main ( S t r i n g a r g s [ ] ) {


l o g g e r . s e v e r e ( SEVERE : H e l l o ) ;
l o g g e r . warning ( WARNING : H e l l o ) ;
l o g g e r . i n f o ( INFO : H e l l o ) ;
}

6
7
8
9
10
11

Programul afiseaza
Jan 23, 2013 2:34:40 PM Exemplu main
SEVERE: SEVERE : Hello
Jan 23, 2013 2:34:40 PM Exemplu main
WARNING: WARNING : Hello
Jan 23, 2013 2:34:40 PM Exemplu main
INFO: INFO : Hello
1
2

Maven acumulator de cunostinte (Idis).


De exemplu repo1.maven.org/maven2.

16

CAPITOLUL 1. APLICAT
II NUMERICE SIMPLE

Daca dorim ca rezultatele sa fie nscrise ntr-un fisier, de exemplu logging.txt atunci clasa
de mai sus se modifica n
1
2
3
4
6
7

import
import
import
import

u t i l . l o g g i n g . Logger ;
u t i l . logging . FileHandler ;
u t i l . l o g g i n g . SimpleFormatter ;
i o . IOException ;

public c l a s s Exemplu{
s t a t i c Logger l o g g e r = Logger . g e t L o g g e r ( Exemplu . c l a s s . getName ( ) ) ;
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
try {
F i l e H a n d l e r l o g g i n g F i l e = new F i l e H a n d l e r ( l o g g i n g . t x t ) ;
l o g g i n g F i l e . s e t F o r m a t t e r (new S i m p l e F o r m a t t e r ( ) ) ;
l o g g e r . addHandler ( l o g g i n g F i l e ) ;
}
catch ( IOException e ) {
System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
}
l o g g e r . s e v e r e ( SEVERE : H e l l o ) ;
l o g g e r . warning ( WARNING : H e l l o ) ;
l o g g e r . i n f o ( INFO : H e l l o ) ;
}

9
10
11
12
13
14
15
16
17
18
19
20
21
22

java .
java .
java .
java .

1.3.2

Verificarea rezultatelor cu junit

junit permite verificarea automata a rezultatelor furnizate de un program, pentru o


multime de date de test.
Utilizarea produsului necesita declararea n variabila de sistem classpath a fisierelor
junit-*.jar, hamcrest-core-*.jar.
Utilizarea produsului ntr-un program Java consta din:
1. Declararea resurselor pachetului junit prin
import org.junit.*;
import static org.junit.Assert.*;
2. Declararea clasei cu testele junit - uzual n metoda main.
org.junit.runner.JUnitCore.main("AppClass");
3. Eventuale operatii necesare nainte sau dupa efectuarea testelor se precizeaza respectiv, n cate o metoda care a fost declarata cu adnotarea @org.junit.Before si
respectiv, @org.junit.After.
4. Testele se definesc n metode declarate cu adnotarea @org.junit.Test.
Clasa Assert poseda metodele de verificare ale unui rezultat:
static void assertEquals(Tip asteptat, Tip actual )
unde Tip poate fi double, int, long, Object.
static void assertEquals(double asteptat, double actual, double delta)
Testul reuseste daca |asteptat-actual | < delta.

1.3. PROBLEME CONEXE

17

static void assertArrayEquals(Tip[ ] asteptat, Tip[ ] actual )


unde Tip poate fi byte, char, int, long, short, Object.
static void assertTrue(boolean conditie)
static void assertFalse(boolean conditie)
static void assertNull(Object object)
static void assertNotNull(Object object)
In cazul exemplului
1
2
4
5
6

import o r g . j u n i t . ;
import s t a t i c o r g . j u n i t . A s s e r t . ;
public c l a s s Exemplu{
public double r e z u l t a t = 1 . 0 ;
public double e p s=1e 6;
double g e t V a l u e ( ) {
return 1 . 0 0 0 0 0 0 1 ;
}

8
9
10

@Test
public void t e s t ( ) {
a s s e r t E q u a l s ( r e z u l t a t , getValue ( ) , eps ) ;
}

12
13
14
15

public s t a t i c void main ( S t r i n g [ ] a r g s ) {


o r g . j u n i t . r u n n e r . JUnitCore . main ( Exemplu ) ;
}

17
18
19
20

se obtine
JUnit version 4.5
.
Time: 0.03
OK (1 test)

1.3.3

Unealta de dezvoltare apache-ant

Incepem aceasta sectiune prin a introduce cateva elemente privind sintaxa ntr-un
document xml pentru ca apache-ant face apel la un fisier xml.
XML
Extensible Markup Language (XML) reprezinta un limbaj pentru definirea marcajelor
de semantica, care mpart un document n parti identificabile n document.
Totodata XML este un meta-limbaj pentru definirea sintaxei de utilizat n alte domenii.
XML descrie structura si semantica si nu formatarea.
Structura unui document XML este
<?xml version="1.0" encoding="ISO-8859-1"?>
corpul documentului alcatuit din elemente

18

CAPITOLUL 1. APLICAT
II NUMERICE SIMPLE

Prima linie reprezinta declaratia de document XML.


Corpul documentului este alcatuit din elemente. Inceputul unui element este indicat
printr-un marcaj. Textul marcajului constituie denumirea elementului. Elementele pot fi
cu corp, alcatuit din alte elemente, avand sintaxa
<marcaj>
corpul elementului
</marcaj>
sau fara corp, caz n care sintaxa este
<marcaj/>
Un marcaj poate avea atribute date prin sintaxa
numeAtribut="valoareAtribut"
Valoarea unui atribut este cuprinsa ntre ghilimele ().
<marcaj numeAtribut="valoareAtribut" . . .>
corpul elementului
</marcaj>
Exista un singur element radacina. Elementele unui document XML formeaza un
arbore. Fiecarui marcaj de nceput al unui element trebuie sa-i corespunda un marcaj de
sfarsit. Caracterele mari si mici din denumirea unui element sunt distincte (case sensitive).
Elementele ncuibarite (nested )- incluse ntr-un alt element - nu se pot amesteca, adica
un marcaj de sfarsit corespunde ultimului marcaj de nceput.
Un comentariu se indica prin
<!-Text comentariu
-->
Exemplul 1.3.1 Fisier XML - denumirile elementelor si continutul lor permit ntelegerea
simpla a semanticii introduse n document.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

<?xml version= 1 . 0 e n c o d i n g= u t f 8 ?>


<c u r s u r i>
< d i s c i p l i n a f e l = o b l i g a t o r i u >
<nume> A n a l i z a numerica </nume>
<fonddetimp>
<c u r s> 2 </ c u r s>
<s e m i n a r> 1 </ s e m i n a r>
<l a b o r a t o r> 1 </ l a b o r a t o r>
</ fonddetimp>
</ d i s c i p l i n a>
< d i s c i p l i n a f e l = o b l i g a t o r i u >
<nume> Programare d i s t r i b u i t a </nume>
<fonddetimp>
<c u r s> 2 </ c u r s>
<s e m i n a r> 0 </ s e m i n a r>

19

1.3. PROBLEME CONEXE

16
17
18
19
20
21
22
23
24
25
26
27

<l a b o r a t o r> 2 </ l a b o r a t o r>


</ fonddetimp>
</ d i s c i p l i n a>
< d i s c i p l i n a f e l = o b l i g a t o r i u >
<nume> S o f t matematic </nume>
<fonddetimp>
<c u r s> 2 </ c u r s>
<s e m i n a r> 0 </ s e m i n a r>
<l a b o r a t o r> 1 </ l a b o r a t o r>
</ fonddetimp>
</ d i s c i p l i n a>
</ c u r s u r i>

Amintim faptul ca reprezentarea obiectelor matematice prin elemente XML constituie subiectul a doua proiecte MathML si OpenMath. Obiectivul limbajului MathML este
reprezentarea unui text matematic ntr-un document HTML, n timp ce obiectivul proiectului OpenMath este reprezentarea semantica a datelor matematice pentru realizarea de
aplicatii cooperante ntre sisteme de calcul simbolic - CAS (Computer Algebra System).
apache-ant
Utilitarul apache-ant asigura executarea unui sir de comenzi de operare. Aceste
comenzi se nregistreaza ntr-un fisier de tip xml, cu denumirea build.xml. Astfel,
apache-ant se substituie unui fisier de comenzi bat n Windows sau unui script shell
din Linux/Unix. Avantajul obtinut consta n independenta fata de platforma de calcul
(Windows, Linux).
Instalarea consta n dezarhivarea fisierului descarcat din Internet.
Lansarea n executie necesita fixarea variabilei de mediu JAVA HOME, ce contine
calea la distributia Java. Lansarea se poate face prin urmatorul fisier de comenzi
set JAVA_HOME=. . .
set ANT_HOME=. . .
%ANT_HOME%\bin\ant.bat %1
Parametrul %1 acestui fisier de comenzi reprezinta obiectivul care se doreste a fi atins.
Daca se modifica denumirea sau locatia fisierului build.xml atunci fisierul de comenzi se
invoca cu optiunea -buildfile.
Un fisier build.xml corespunde unui proiect (project), alcatuit din unul sau mai multe
obiective (target). Atingerea fiecararui obiectiv consta din ndeplinirea uneia sau mai
multor sarcini (task). Apache-ant contine o familie predefinita de sarcini. Programatorul
are datoria fixarii atributelor sarcinilor. Manualul din documentatia produsului contine
descrierea atributelor cat si exemple. In general, o sarcina reprezinta o operatie executata
uzual n linia de comanda.
Atributele se dau, respectand sintaxa XML
numeAtribut = valoareAtribut
Astfel, un proiect apare sub forma

20

CAPITOLUL 1. APLICAT
II NUMERICE SIMPLE

<project name="numeProiect"
default="obiectiv"
basedir="catalogDeReferinta">
<target name="numeObiectiv">
sarcini
</target>
. . . . . . .
</project>
Daca la apelarea lui Apache-ant lipseste parametrul optional atunci se va executa
obiectivul default.
Intr-un proiect se pot defini variabile prin elementul
<property name=numeVariabila value=valoareVariabila />
O variabila definita se va utiliza cu sintaxa ${numeVariabila}.

1.3.4

Gestiunea proiectelor cu apache-maven

Instalarea produsului consta n dezarhivarea fisierului descarcat din Internet ntr-un


catalog a carei cale este fixata n variabila de mediu MAVEN HOME.
Utilizarea produsului necesita
Completarea variabilei de sistem PATH cu calea MAVEN HOME\bin.
Declararea variabilei JAVA HOME avand ca valoare calea catre distributia jdk folosita.
In mod obisnuit depozitul local maven este
C:\Documents and Settings\client\.m2\repository
Locatia depozitului local se poate modifica, introducand elementul
<localRepository>volum:/cale/catalog_depozit</localRepository>
n fisierul MAVEN HOME\conf\settings.xml.
Potrivit principiului separarii preocuparilor (Separation of Conserns), un proiect maven
produce o singura iesire.
Declararea unui proiect se face printr-un fisier pom.xml (Project Object Model). Este
sarcina programatorului sa completeze fisierul pom.xml, creat la generarea structurii de
cataloage ale proiectului, cu specificarea resurselor suplimentare sau a conditionarilor n
efectuarea unor operatii (de exemplu, prezenta adnotarilor necesita utilizarea unei versiuni
Java mai mare dacat 1.5).
Dezvoltarea unei aplicatii / proiect prin maven presupune generarea unei structuri de
cataloage (Standard directory layout for projects). Aceasta structura de cataloage este
specifica tipului / sablonului de aplicatie (archetype, n limbajul maven).
Sabloane uzuale de aplicatii:

1.3. PROBLEME CONEXE

21

Nume sablon
Semnificatia
maven-archetype-quickstart aplicatie simpla
(sablonul implicit)
maven-archetype-webapp
aplicatie Web
Indeplinirea diferitelor obiective (generarea unui proiect, compilare, arhivare, testare,
etc) se obtin prin comenzi maven.
Comenzile maven sunt de doua tipuri:

Comenzi pentru gestiunea ciclului de viata al unui proiect (lifecycle commands):

Comanda maven
mvn -version

Semnificatia
afiseaza versiunea lui maven
(utila pentru verificarea functionarii lui maven)
mvn clean
sterge fisierele maven generate
mvn compile
compileaza sursele Java
mvn test-compile compileaza sursele Java care
realizeaza testele junit
mvn test
executa testul junit
mvn package
creaza o arhiva jar sau war
mvn install
depune arhiva jar sau war n depozitul local

Comenzi de operare inserate (plugin commands):

22

CAPITOLUL 1. APLICAT
II NUMERICE SIMPLE

Comanda maven
mvn -B archetype:generate

Semnificatia
genereaza structura de cataloage a proiectului
Optiunea -B are ca efect generarea
neinteractiva.
mvn -B archetype:generate \
-DgroupId=numelePachetuluiAplicatiei \
-DartifactId=numeleProiectului \
-DarchetypeArtifactId=numeS
ablon\
-Dversion=versiuneaProiectului

mvn
mvn
mvn
mvn
mvn

clean:clean
compiler:compile
surefire:test
jar:jar
install:install-file

sterge fisierele generate n urma compilarii


compileaza sursele Java
executa testul junit
creaza o arhiva jar
depune o arhiva jar n depozitul local
mvn install:install-file \
-Dfile=numeFisier \
-DgroupId=numePachet \
-DartifactId=numeProiect \
-Dversion=versiunea \
-Dpackaging=tipArhiv
a

mvn exec:java

executa metoda main a unei clase


mvn exec:java \

mvn dependency:copy-dependencies

-Dexec.mainClass=clasaMetodeiMain
descarca n catalogul target resursele
declarate n dependencies.

Astfel comanda
mvn -B archetype:generate -DgroupId=unitbv.cs.calcul -DartifactId=hello -Dversion=1.0

genereaza arborescenta
hello
|--> src
|
|--> main
|
|
|-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|--> test
|
|
|-->
|
|
|
|
|
|
|
|
|
|
|
|
|
pom.xml

java
|-->
|
|
|

unitbv
|--> cs
|
|--> calcul
|
|
| App.java

java
|-->
|
|
|

unitbv
|--> cs
|
|--> calcul
|
|
|
AppTest.java

Descrierea proiectului este data n fisierul pom.xml generat


1
2
3

<p r o j e c t xmlns= h t t p : //maven . apache . o r g /POM/ 4 . 0 . 0


x m l n s : x s i= h t t p : //www. w3 . o r g /2001/XMLSchemai n s t a n c e
x s i : s c h e m a L o c a t i o n= h t t p : //maven . apache . o r g /POM/ 4 . 0 . 0

1.3. PROBLEME CONEXE

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

23

h t t p : //maven . apache . o r g /mavenv 4 0 0 . xsd >


<m o d e l V e r s i o n> 4 . 0 . 0</ m o d e l V e r s i o n>
<g r o u p I d>u n i t b v . c s . c a l c u l</ g r o u p I d>
< a r t i f a c t I d> h e l l o</ a r t i f a c t I d>
<p a c k a g i n g>j a r</ p a c k a g i n g>
<version>1 . 0</ version>
<name> h e l l o</name>
<u r l>h t t p : //maven . apache . o r g</ u r l>
<d e p e n d e n c i e s>
<dependency>
<g r o u p I d>j u n i t</ g r o u p I d>
< a r t i f a c t I d>j u n i t</ a r t i f a c t I d>
<version> 3 . 8 . 1</ version>
<s c o p e> t e s t</ s c o p e>
</ dependency>
</ d e p e n d e n c i e s>
</ p r o j e c t>

App.java este programul Java HelloWorld iar AppTest.java este un program de verificare bazat pe junit.
Pentru testarea aplicatiei, din catalogul hello, se executa comenzile
mvn compile
mvn test

Executia programului se poate lansa prin intermediul unui profil (profile)


mvn exec:java -PnumeProfil

In prealabil n fisierul pom.xml se introduce secventa


<profiles>
<profile>
<id>numeProfil</id>
<properties>
<target.main.class>clasaCuMetodaMain</target.main.class>
</properties>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<configuration>
<mainClass>${target.main.class}</mainClass>
<includePluginDependencies>false</includePluginDependencies>
</configuration>
</plugin>
</plugins>
</build>

Aceasta varianta este avantajoasa n cazul n care proiectul include mai multe clase cu
metoda main.
Sarcina programatorul este acela de a nlocui aceste programe cu cele care rezolva
sarcinile proiectului. Pentru orice prelucrare toate dependintele trebuie sa se gaseasca
n depozitul local maven. Daca o dependinta (resursa jar) nu se gaseste n depozitul
local atunci resursa este cautata ntr-un depozit global si este descarcata n depozitul
global. Este sarcina programatorului sa declare toate dependintele necesare unei aplicatii.
Declararea se face ntr-un element <dependency>. Daca resursa este inaccesibila atunci
maven termina prelucrarea.

24

CAPITOLUL 1. APLICAT
II NUMERICE SIMPLE

Programatorul are posibilitatea sa specifice depozite globale unde sa se gaseasca resursele


necesare, de exemplu
<repositories>
<repository>
<id>java.net-promoted</id>
<url>https://maven.java.net/content/groups/promoted/</url>
</repository>
</repositories>

Se pot defini variabile n elementul


<properties>
<nume.proprietate>valoare</nume.proprietate>
. . .
</properties>

O variabila se indica la fel ca n apache-ant, prin ${nume.proprietate}.


In maven se pot integra sarcini apache-ant pentru orice etapa al evolutiei unei aplicatii.
Utilizarea consta n completarea fisierului pom.xml cu
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>
<!-- etapa de viata : compile, package, install, test -->
</phase>
<configuration>
<tasks>
<!-- Exemplu
<property name="compile_classpath" refid="maven.compile.classpath"/>
<property name="runtime_classpath" refid="maven.runtime.classpath"/>
<property name="test_classpath" refid="maven.test.classpath"/>
<property name="plugin_classpath" refid="maven.plugin.classpath"/>
<echo message="compile classpath:
<echo message="runtime classpath:
<echo message="test classpath:
<echo message="plugin classpath:
-->
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

${compile_classpath}"/>
${runtime_classpath}"/>
${test_classpath}"/>
${plugin_classpath}"/>

In elementul <tasks> se definesc sarcinile ant care se doresc executate la comanda corespunzatoare prelucrarii etapei din evolutia proiectului maven - compile, package, install,
test, etc.

NUMERICA

1.4. O MINI-BIBLIOTECA

1.4

25

O mini-bibliotec
a numeric
a

Programele corespunzatoare metodelor de calcul (metoda tangentei si metoda Simpson) le vom include ntr-o mini-biblioteca. Aceasta biblioteca va fi valorificata n capitolele urmatoare, prin dezvoltarea de programe client cu interfete grafice prietenoase si
prin apelarea resurselor mini-bibliotecii de la distanta.
In timpul programarii apare problema transmiterii datelor catre campurile claselor sau
catre parametrii metodelor. Probleme apar si n cazul rezultatelor returnate de metode.
Deseori printre date se afla expresii ale unor functii matematice.
Semnalam urmatoarele posibilitati de programare a transmiterii datelor:
Datele - mai putin functiile - se transmit ca si parametri iar o functie se poate defini
ntr-o clasa care eventual implementeaza o interfata predefinita. O instanta a unei
asemenea clase se transmite de asemenea ca parametru. Aceasta solutie corespunde
modului de programare din Fortran sau C [7].
Prin clase acoperitoare a datelor si respectiv, a rezultatelor.
Varianta n care o functie este data prin expresia ei de calcul fixata printr-un sir de
caractere (string) va fi tratata n Cap. 5.
In continuare, varianta adoptata va fi cea n care datele se transmit prin clase acoperitoare. Avantajul acestei solutii este dat de flexibilitatea oferita de paradigma programarii
orientate pe obiecte, iar dezavantajul consta n cerinta ca un utilizator (client) sa aiba
cunostinte de programare orientata pe obiecte.
Pentru fiecare tip de problema, mini-biblioteca va contine:
o interfata n care se declara metodele disponibile;
o implementare a interfetei.
Astfel, se ofera posibilitatea dezvoltarii si utilizarii mai multor implementari ale aceleiasi
metode.
Clasele Java prin care se transmitit datele de intrare (DataIn) si cele de iesire (DataOut)
sunt incluse n pachetele interfetelor corespunzatoare. Aceste clase sunt componente Java
(bean).
Desfasurarea mini-bibliotecii mathlib cu programele sursa este
lib
|
log4j-*.jar
src
|--> mathlib
|
|--> client
|
|
|--> ecalg
|
|
|
|--> impl
|
|
|
|
|
MetodaTangentei.java // implementeaza interfata
|
|
|
|
IMetodaTangentei.java
// interfata
|
|
|
|
DataIn.java
|
|
|
|
DataOut.java
|
|
|--> cvadra
|
|
|
|--> impl
|
|
|
|
|
MetodaSimpson.java // implementeaza interfata
|
|
|
|
IMetodaSimpson.java
// interfata
|
|
|
|
DataIn.java
|
|
|
|
DataOut.java

26

CAPITOLUL 1. APLICAT
II NUMERICE SIMPLE

Utilizarea mini-bibliotecii ca un modul Google Web Toolkit impune intercalarea catalogului client.
Codurile claselor / interfetelor sunt:
1. Clasa mathlib.client.ecalg.IMetodaTangentei
1
2
3
4
5
6
7
8
9
10

package m a t h l i b . c l i e n t . e c a l g ;
/
I n t e r f a t a metodei t a n g e n t e i .
/
p u b l i c i n t e r f a c e IMetodaTangentei {
/
Metoda t a n g e n t e i .
/
p u b l i c DataOut metodaTangentei ( DataIn d i n ) ;
}

2. Clasa mathlib.client.ecalg.DataIn
1
2
3
4
5
6
7
8
9
11
12
13
14
16
17
18
19
20
21
22
23
24
25
26
27
29
30
31
32
33
34
35
36
37
38
39
40
42
43
44
45
46

package m a t h l i b . c l i e n t . e c a l g ;
/
Clasa a c o p e r i t o a r e a d a t e l o r necesare r e z o l v a r i i
unei e c u a t i i a l g e b r i c e
/
public abstract c l a s s DataIn {
private double x ;
// a p r o x i m a t i a i n i t i a l a
private double e p s ; // t o l e r a n t a admisa
private i n t nmi ;
// numar maxim admis de i t e r a t i i
/
F u n c t i a c o r e s p u n z a t i o a r e membrului s t a n g a l e c u a t i e i f c t ( x )=0.
/
public abstract double f c t ( double x ) ;
/
Fixeaza aproximatia s o l u t i e i .
/
public void setX ( double x ) {
t h i s . x=x ;
}
/
F i x e a z a e x t r e m i t a t e a i n f e r i o a r a a i n t e r v a l u l u i de i n t e g r a r e
/
public double getX ( ) {
return x ;
}
/
Fixeaza t o l e r a n t a .
/
public void s e t E p s ( double e p s ) {
t h i s . e p s=e p s ;
}
/
Returneaza t o l e r a n t a .
/
public double getEps ( ) {
return e p s ;
}
/
F i x e a z a numarul maxim admis de i t e r a t i i .
/
public void setNmi ( i n t nmi ) {
t h i s . nmi=nmi ;

NUMERICA

1.4. O MINI-BIBLIOTECA

}
/
Returneaza numarul maxim admis de i t e r a t i i .
/
public i n t getNmi ( ) {
return nmi ;
}

47
48
49
50
51
52
53
54

3. Clasa mathlib.client.ecalg.DataOut
1
2
3
4
5
6
7
8
9
10
12
13
14
15
16
17
18
19
20
21
22
23
25
26
27
28
29
30
31
32
33
34
35
36
37
38
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

package m a t h l i b . c l i e n t . e c a l g ;
/
Clasa a c o p e r i t o a r e a r e z u l t a t e l o r o b t i n u t e
l a r e z o l v a r e a unei e c u a t i i a l g e b r i c e
/
public c l a s s DataOut {
private double x ;
// a p r o x i m a t i a c a l c u l a t a a s o l u t i e i
private i n t i n d ;
// i n d i c a t o r u l de r a s p u n s a l p r o g r a m u l u i
private double f ;
// v a l o a r e a e x p r e s i e i s t a n g i a e c u a t i e i i n x
private i n t n i ;
// numarul i t e r a t i i l o r e f e c t u a t e
/
Returneaza a p r o x i m a t i a s o l u t i e i .
/
public double getX ( ) {
return x ;
}
/
Fixeaza aproximatia s o l u t i e i .
/
public void setX ( double x ) {
t h i s . x=x ;
}
/
Returneaza v a l o a r e a membrului s t a n g a l e c u a t i e i c a l c u l a t a
in aproximatia f i x a t a a s o l u t i e i e c u a t i e i .
/
public double getF ( ) {
return f ;
}
/
F i x e a z a v a l o a r e a membrului s t a n g a l e c u a t i e i c a l c u l a t a
in aproximatia c a l c u l a t a a s o l u t i e i e c u a t i e i .
/
public void s e t F ( double f ) {
t h i s . f=f ;
}
/
Returneaza i n d i c a t o r u l de r a s p u n s .

0 succes ;
1 insucces .
2 s i n g u l a r i t a t e d e p i s t a t a in timpul c a l c u l u l u i .
/
public i n t g e t I n d ( ) {
return i n d ;
}
/
F i x e a z a i n d i c a t o r u l de r a s p u n s .
/
public void s e t I n d ( i n t i n d ) {
t h i s . i n d=i n d ;
}

27

28

CAPITOLUL 1. APLICAT
II NUMERICE SIMPLE

/
Returneaza numarul i t e r a t i i l o r e f e c t u a t e .
/
public i n t g e t N i ( ) {
return n i ;
}
/
F i x e a z a numarul i t e r a t i i l o r e f e c t u a t e .
/
public void s e t N i ( i n t n i ) {
t h i s . n i=n i ;
}

57
58
59
60
61
62
63
64
65
66
67
68
69

4. Clasa mathlib.client.ecalg.impl.MetodaTangentei
1
2
3
4
5
6
7
8
10
11
12
13
14
15
17
18
19
20
21
22
23
24
25
26
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

package m a t h l i b . c l i e n t . e c a l g . impl ;
import j a v a . u t i l . l o g g i n g . Logger ;
import j a v a . u t i l . l o g g i n g . F i l e H a n d l e r ;
import j a v a . u t i l . l o g g i n g . S i m p l e F o r m a t t e r ;
import m a t h l i b . c l i e n t . e c a l g . DataIn ;
import m a t h l i b . c l i e n t . e c a l g . DataOut ;
import m a t h l i b . c l i e n t . e c a l g . IMetodaTangentei ;
import j a v a . i o . IOException ;
/
Implementarea m e t o d e i t a n g e n t e i .
V a r i a n t a cu i n r e g i s t r a r e a r e z u l t a t e l o r i n t e r m e d i a r e ( l o g ) .
/
public c l a s s MetodaTangentei implements IMetodaTangentei {
s t a t i c Logger l o g g e r = Logger . g e t L o g g e r ( MetodaTangentei . c l a s s . getName ( ) ) ;
public MetodaTangentei ( ) {
try {
F i l e H a n d l e r l o g g i n g F i l e = new F i l e H a n d l e r ( r e s u l t s E c a l g . l o g ) ;
l o g g i n g F i l e . s e t F o r m a t t e r (new S i m p l e F o r m a t t e r ( ) ) ;
l o g g e r . addHandler ( l o g g i n g F i l e ) ;
}
catch ( IOException e ) {
System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
}
}
/
Metoda t a n g e n t e i a p l i c a t a d a t e l o r f i x a t e i n o b i e c t u l d i n .
/
public DataOut metodaTangentei ( DataIn d i n ) {
double x , y=d i n . getX ( ) , d , f , df , e p s=d i n . getEps ( ) ;
i n t nmi=d i n . getNmi ( ) ;
DataOut dout=new DataOut ( ) ;
i n t n i =0;
do{
n i ++;
x=y ;
f=d i n . f c t ( x ) ;
d f=d f c t ( x , d i n ) ;
y=xf / d f ;
i f ( ( y==Double . NaN ) | | ( Math . abs ( y)==Double . POSITIVE INFINITY ) ) {
dout . s e t I n d ( 2 ) ;
dout . setX ( y ) ;
dout . s e t F ( Double . NaN ) ;
dout . s e t N i ( n i ) ;
return dout ;
}
d=Math . abs ( ( yx ) ) ;

29

NUMERICA

1.4. O MINI-BIBLIOTECA

S t r i n g mesaj= i t e r = +n i+ s o l u t i a = +x+ e r o a r e a = +d ;
l o g g e r . i n f o ( mesaj ) ;

50
51

}
while ( ( d>=e p s ) && ( ni <nmi ) ) ;
i f ( d<e p s )
dout . s e t I n d ( 0 ) ;
else
dout . s e t I n d ( 1 ) ;
dout . setX ( x ) ;
dout . s e t F ( d i n . f c t ( x ) ) ;
dout . s e t N i ( n i ) ;
return dout ;

52
53
54
55
56
57
58
59
60
61
62

64

/
C a l c u l u l d e r i v a t e i de o r d i n u l i n t a i .
@param x P u n c t u l i n c a r e s e c a l c u l e a z a d e r i v a t a .
@param d i n O b i e c t DataIn c a r e c o n t i n e d e f i n i t i a f u n c t i e i a c a r e i d e r i v a t a
se c a l c u l e a z a .
/
private double d f c t ( double x , DataIn d i n ) {
i n t m=6;
double h=1e 10;
double pk =1; // 4 k
double [ ] [ ] d=new double [m ] [ m ] ;
f o r ( i n t i =0; i <m; i ++)
d [ i ] [ 0 ] = 0 . 5 ( d i n . f c t ( x+h) d i n . f c t ( xh ) ) / h ;
f o r ( i n t j =1; j <m; j ++){
pk=4pk ;
f o r ( i n t i=j ; i <m; i ++){
d [ i ] [ j ]=( pkd [ i ] [ j 1]d [ i 1 ] [ j 1 ] ) / ( pk 1);
}
}
return d [m 1 ] [m 1 ] ;
}

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

5. Clasa mathlib.client.cvadra.IMetodaSimpson
1
2
3
4
5
6
7
8
9
10

package m a t h l i b . c l i e n t . c v a d r a ;
/
I n t e r f a t a m e t o d e i Simpson .
/
public i n t e r f a c e IMetodaSimpson {
/
Metoda Simpson .
/
public DataOut metodaSimpson ( DataIn d i n ) ;
}

6. Clasa mathlib.client.cvadra.DataIn
1
2
3
4
5
6

package m a t h l i b . c l i e n t . c v a d r a ;
/
Clasa a c o p e r i t o a r e a d a t e l o r necesare c a l c u l u i
unei i n t e g r a l e .
/
public abstract c l a s s DataIn {

11

private
private
private
private

13

8
9
10

double a ;
double b ;
double e p s ;
i n t nmi ;

//
//
//
//

extremitatea stanga
extremitatea dreapta
t o l e r a n t a admisa
numar maxim admis de i t e r a t i i

30

CAPITOLUL 1. APLICAT
II NUMERICE SIMPLE

Functia i n t e g r a t a .
/
public abstract double f c t ( double x ) ;

14
15
16

/
Returneaza e x t r e m i t a t e a i n f e r i o a r a a i n t e r v a l u l u i de i n t e g r a r e .
/
public double getA ( ) {
return a ;
}
/
F i x e a z a e x t r e m i t a t e a i n f e r i o a r a a i n t e r v a l u l u i de i n t e g r a r e .
/
public void setA ( double a ) {
t h i s . a=a ;
}

18
19
20
21
22
23
24
25
26
27
28
29

/
Returneaza e x t r e m i t a t e a s u p e r i o a r a a i n t e r v a l u l u i de i n t e g r a r e .
/
public double getB ( ) {
return b ;
}
/
F i x e a z a e x t r e m i t a t e a s u p e r i o r a a i n t e r v a l u l u i de i n t e g r a r e .
/
public void setB ( double b ) {
t h i s . b=b ;
}

31
32
33
34
35
36
37
38
39
40
41
42

/
Fixeza t o l e r a n t a .
/
public void s e t E p s ( double e p s ) {
t h i s . e p s=e p s ;
}
/
Returneaza t o l e r a n t a .
/
public double getEps ( ) {
return e p s ;
}

44
45
46
47
48
49
50
51
52
53
54
55

/
F i x e a z a numarul maxim admis de i t e r a t i i .
/
public void setNmi ( i n t nmi ) {
t h i s . nmi=nmi ;
}
/
Returneaza numarul maxim admis de i t e r a t i i .
/
public i n t getNmi ( ) {
return nmi ;
}

57
58
59
60
61
62
63
64
65
66
67
68
69

7. Clasa mathlib.client.cvadra.DataOut
1
2
3
4
5
6
7

package m a t h l i b . c l i e n t . c v a d r a ;
/
Clasa a c o p e r i t o a r e a r e z u l t a t e l o r o b t i n u t e
l a c a l c u l u l unei i n t e g r a l e .
/
public c l a s s DataOut{
private double i n t e g r a l a ; // i n t e g r a l a

31

NUMERICA

1.4. O MINI-BIBLIOTECA

private i n t i n d ;
private i n t n i ;

8
9

/
Returneaza v a l o a r e a i n t e g r a l e i .
/
public double g e t I n t e g r a l a ( ) {
return i n t e g r a l a ;
}
/
Fixeaza valoarea i n t e g r a l e i .
/
public void s e t I n t e g r a l a ( double i n t e g r a l a ) {
t h i s . i n t e g r a l a=i n t e g r a l a ;
}

11
12
13
14
15
16
17
18
19
20
21
22

/
Returneaza i n d i c a t o r u l de r a s p u n s .

0 succes ;
1 insucces .
/
public i n t g e t I n d ( ) {
return i n d ;
}
/
F i x e a z a i n d i c a t o r u l de r a s p u n s .
/
public void s e t I n d ( i n t i n d ) {
t h i s . i n d=i n d ;
}

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

/
Returneaza numarul i t e r a t i i l o r e f e c t u a t e .
/
public i n t g e t N i ( ) {
return n i ;
}
/
F i x e a z a numarul i t e r a t i i l o r e f e c t u a t e .
/
public void s e t N i ( i n t n i ) {
t h i s . n i=n i ;
}

40
41
42
43
44
45
46
47
48
49
50
51
52

// i n d i c a t o r u l de r a s p u n s a l p r o g r a m u l u i
// numarul i t e r a t i i l o r e f e c t u a t e

8. Clasa mathlib.client.cvadra.impl.MetodaSimpson
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
17
18

package m a t h l i b . c l i e n t . c v a d r a . impl ;
import j a v a . u t i l . l o g g i n g . Logger ;
import j a v a . u t i l . l o g g i n g . F i l e H a n d l e r ;
import j a v a . u t i l . l o g g i n g . S i m p l e F o r m a t t e r ;
import m a t h l i b . c l i e n t . c v a d r a . DataIn ;
import m a t h l i b . c l i e n t . c v a d r a . DataOut ;
import m a t h l i b . c l i e n t . c v a d r a . IMetodaSimpson ;
import j a v a . i o . IOException ;
/
Implementarea m e t o d e i Simpson .
V a r i a n t a cu i n r e g i s t r a r e a r e z u l t a t e l o r i n t e r m e d i a r e ( l o g ) .
/
public c l a s s MetodaSimpson implements IMetodaSimpson {
private double s=Double . NaN ;
s t a t i c Logger l o g g e r = Logger . g e t L o g g e r ( MetodaSimpson . c l a s s . getName ( ) ) ;
public MetodaSimpson ( ) {
try {

32

CAPITOLUL 1. APLICAT
II NUMERICE SIMPLE

F i l e H a n d l e r l o g g i n g F i l e = new F i l e H a n d l e r ( r e s u l t s I n t e g . l o g ) ;
l o g g i n g F i l e . s e t F o r m a t t e r (new S i m p l e F o r m a t t e r ( ) ) ;
l o g g e r . addHandler ( l o g g i n g F i l e ) ;

19
20
21

}
catch ( IOException e ) {
System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
}

22
23
24
25
26

28

/
Formula Simpson de a p l i c a r e p r a c t i c a cu
parametru de d i s c r e t i z a r e f i x a t .
La prima a p e l a r e s=Double .NaN !

29
30
31

/
private double simpson ( i n t m, DataIn d i n ) {
double a=d i n . getA ( ) , b=d i n . getB ( ) ;
double h = 0. 5( ba ) /m;
double sp =0 , s i =0;
i f ( Double . isNaN ( s ) ) {
f o r ( i n t i =1; i <m; i ++)
sp+=d i n . f c t ( a+2 i h ) ;
}
else
sp=s ;
f o r ( i n t i =0; i <m; i ++)
s i+=d i n . f c t ( a +(2 i +1)h ) ;
s=sp+s i ;
return h ( d i n . f c t ( a)+ d i n . f c t ( b)+2 sp+4 s i ) / 3 ;
}

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

/
Schema a d a p t i v a p e n t r u metoda l u i Simpson .
A l g o r i t m i t e r a t i v cu r e g u l a de o p r i r e .
/
public DataOut metodaSimpson ( DataIn d i n ) {
double i n t v , i n t n , d , e p s=d i n . getEps ( ) ;
i n t nmi=d i n . getNmi ( ) ;
i n t m=2;
// Parametrul de d i s c r e t i z a r e
i n t n=simpson (m, d i n ) ;
DataOut dout=new DataOut ( ) ;
i n t n i =0;
do{
n i ++;
i n t v=i n t n ;
m=2m;
i n t n=simpson (m, d i n ) ;
d=Math . abs ( i n t n i n t v ) ;
S t r i n g mesaj= i t e r = +n i+ i n t e g r a l a = +i n t n+ e r o a r e a = +d ;
l o g g e r . i n f o ( mesaj ) ;
}
while ( ( d>=e p s ) && ( ni <nmi ) ) ;
i f ( d<e p s )
dout . s e t I n d ( 0 ) ;
else
dout . s e t I n d ( 1 ) ;
dout . s e t I n t e g r a l a ( i n t n ) ;
dout . s e t N i ( n i ) ;
return dout ;
}

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

Aceasta mini-biblioteca va fi extinsa pe parcursul lucrarii, adaugand clase noi.


Compilarea si arhivarea claselor se realizeaza prin intermediul lui apache-ant cu urmatorul
fisier build.xml :

1.5. FORMATAREA REZULTATETOR

1
2

<?xml version= 1 . 0 e n c o d i n g= UTF8 ?>


<project name= p r o i e c t b a s e d i r= . d e f a u l t= ToJar >

<property name= package v a l u e= m a t h l i b />

<property
<property
<property
<property

7
8
9
11
12
13
14
15
16
18
19
20
21
22
24
25
26
27
28
29
30
32
33
34
36
37
38
39
40
41

33

name= l i b . d i r v a l u e= l i b />
name= b u i l d . d i r v a l u e= b u i l d />
name= d i s t . d i r v a l u e= d i s t />
name= d i s t . name v a l u e= m a t h l i b />

<path i d= p a t h r e f >
< f i l e s e t d i r= ${ l i b . d i r } >
<include name= . j a r />
</ f i l e s e t>
<pathelement path= ${ b u i l d . d i r } />
</path>
<target name= I n i t >
<mkdir d i r= ${ b u i l d . d i r } />
<delete d i r= ${ d i s t . d i r } />
<mkdir d i r= ${ d i s t . d i r } />
</ target>
<target name= Compile depends= I n i t description= c o m p i l e >
<javac s r c d i r= s r c /${ package }
d e s t d i r= ${ b u i l d . d i r }
i n c l u d e a n t r u n t i m e= f a l s e >
<classpath r e f i d= p a t h r e f />
</ javac>
</ target>
<target name= ToJar depends= Compile >
<j a r d e s t f i l e = ${ d i s t . d i r }/${ d i s t . name } . j a r b a s e d i r= ${ b u i l d . d i r } />
</ target>
<target name= Docs >
<delete d i r= d o c s />
<mkdir d i r= d o c s />
<javadoc d e s t d i r= d o c s sourcepath= s r c />
</ target>
</ project>

Arhiva mathlib.jar care rezulta, va fi utilizata de programele client. In urma oricarei


modificari efectuata n mini-biblioteca trebuie recreata arhiva mathlib.jar.
Ori de cate ori se folosesc resursele mini-bibliotecii, variabila de sistem classpath
trebuie sa localizeze fisierul mathlib.jar.

1.5

Formatarea rezultatetor

Este un deziderat ca afisarea valorii unei variabile - de obicei un numar reprezentat n


virgula mobila - sa contina doar cifrele ei semnificative, adica cele care nu sunt influentate
de erorile de rotunjire, care apar n urma reprezentarii si calculelor n virgula mobila, dar
si de eroarea de metoda.
Afisarea valorii variabilei - de exemplu r - prin System.out.println(r) se face cu
un numar de zecimale, iar de la o anumita pozitie cifrele sunt influentate de erorile de
rotunjire si de roarea de metoda.
Astfel apare cerinta ca programatorul sa specifice numarul de zecimale care sa fie
afisat, cu alte cuvinte sa formateze rezultatul.

34

CAPITOLUL 1. APLICAT
II NUMERICE SIMPLE

Atunci cand afisarea are loc de un program desktop, formatarea se face cu metoda
printf a clasei PrintWriter. Formate uzuale sunt %m.nX unde
m - este numarul caracterelor;
n - este numarul zecimalelor;
X {e, f, g}; e - reprezentare stiintifica; f - reprezentare zecimala; g combinatie
ntre reprezentare stiintifica si zecimala.
Daca rezultatul apare prin intermediul unui program navigator, atunci se pot utiliza
sablonul
import java.text.DecimalFormat;
. . .
DecimalFormat df=new DecimalFormat("0.00001");
out.println(df.format(r));
. . .

unde out este fluxul de iesire.


metoda format(String format,Object . . . args) a clasei java.io.PrintWriter. O
descriere amanuntita a modului de formatare este data n documentatia ce nsoteste
distributia jdk. Prezentam doar cazul unei variabile numerice r de tip float sau
double care se afiseaza pe l = 12 pozitii cu d = 6 cifre zecimale. Codul Java este
import java.io.PrintWriter;
. . .
PrintWriter out=. . .
out.format("r = %1$12.6f",r);
. . .

1.6

Rezolvarea problemelor

Deoarece clasele de tip DataIn ale mini-bibliotecii nu contin codul functiei specifice
unei probleme concrete, ele au fost declarate clase abstract. Un client trebuie sa extinda
o asemenea clasa specificand metoda double fct(double x).

Calculul solutiei negative a ecuatiei 2x x2 = 0


Aplicatia client contine clasele SimpluEcAlgDataIn - cu fixarea functiei - si TestEcAlg
- cu metoda main - avand respectiv codurile
1
2

import m a t h l i b . c l i e n t . e c a l g . DataIn ;
public c l a s s SimpluEcAlgDataIn extends DataIn {
// membrul s t a n g a l e c u a t i e i
SimpluEcAlgDataIn ( ) {
setX ( 0 . 5 ) ;
// a p r o x i m a t i a i n i t i a l a
s e t E p s ( 1 e 8);
// t o l e r a n t a admisa
setNmi ( 5 0 ) ;
// numar maxim admis de i t e r a t i i
}

4
5
6
7
8
9

public double f c t ( double x ) {


return Math . exp ( xMath . l o g (2)) xx ;
}

11
12
13
14

35

1.6. REZOLVAREA PROBLEMELOR

si
1
2
3
4
6
7
8
9
10

import
import
import
import

public c l a s s TestEcAlg {
// r e z u l t a t u l c u n o s c u t a l e c u a t i e i
private double r e z u l t a t = 0.7666647;
private DataIn d i n ;
private DataOut dout ;
@Before
public void i n i t i a l i z a r e ( ) {
d i n=new SimpluEcAlgDataIn ( ) ;
IMetodaTangentei o b j=new MetodaTangentei ( ) ;
dout=o b j . metodaTangentei ( d i n ) ;
}

12
13
14
15
16
17

@Test
public void t e s t ( ) {
a s s e r t E q u a l s ( r e z u l t a t , dout . getX ( ) , d i n . getEps ( ) ) ;
}

19
20
21
22

@After
public void a f i s a r e ( ) {
System . out . p r i n t l n ( \ n I n d i c a t o r u l de r a s p u n s : +dout . g e t I n d ( ) ) ;
System . out . p r i n t f ( S o l u t i a e c u a t i e i : %16.8 f \n , dout . getX ( ) ) ;
System . out . p r i n t f ( V a l o a r e a f u n c t i e i i n s o l u t i e : %16.8 e \n , dout . getF ( ) ) ;
System . out . p r i n t l n ( Numarul i t e r a t i i l o r e f e c t u a t e : +dout . g e t N i ( ) ) ;
}

24
25
26
27
28
29
30

public s t a t i c void main ( S t r i n g [ ] a r g s ) {


o r g . j u n i t . r u n n e r . JUnitCore . main ( TestEcAlg ) ;
}

32
33
34
35

org . j u n i t . ;
static org . j u n i t . Assert . ;
mathlib . c l i e n t . e c a l g . ;
m a t h l i b . c l i e n t . e c a l g . impl . ;

Se utilizeaza junit pentru verificarea rezultatului furnizat de aplicatie cu solutia cunoscuta.


Rezultatele afisate sunt
Indicatorul de raspuns : 0
Solutia ecuatiei :
-0.76666470
Valoarea functiei in solutie : -5.14033260e-14
Numarul iteratiilor efectuate : 5
Time: 0.13
OK (1 test)

Calculul integralei

R
4

ln(1 + tan x)dx

In mod asemanator aplicatia client este alcatuita din clasele


1
2
3
4
5
6
7
8
10
11

import m a t h l i b . c l i e n t . c v a d r a . DataIn ;
public c l a s s SimpluCvadraDataIn extends DataIn {
SimpluCvadraDataIn ( ) {
setA ( 0 ) ;
// e x t r e m i t a t e a s t a n g a
setB ( 0 . 2 5 Math . PI ) ;
// e x t r e m i t a t e a d r e a p t a
s e t E p s ( 1 e 12);
// t o l e r a n t a admisa
setNmi ( 5 0 ) ;
// numar maxim admis de i t e r a t i i
}
// f u n c t i a de i n t e g r a t
public double f c t ( double x ) {

36

return Math . l o g (1+Math . tan ( x ) ) ;

12

13
14

CAPITOLUL 1. APLICAT
II NUMERICE SIMPLE

si
1
2
3
4
6
7
8
9
10

import
import
import
import

public c l a s s T e s t I n t e g r a l a {
// r e z u l t a t u l c u n o s c u t a l i n t e g r a l e i
private double r e z u l t a t =0.125Math . PI Math . l o g ( 2 ) ;
private DataIn d i n ;
private DataOut dout ;
@Before
public void i n i t i a l i z a r e ( ) {
d i n=new SimpluCvadraDataIn ( ) ;
IMetodaSimpson o b j=new MetodaSimpson ( ) ;
dout=o b j . metodaSimpson ( d i n ) ;
}

12
13
14
15
16
17

@Test
public void t e s t ( ) {
a s s e r t E q u a l s ( r e z u l t a t , dout . g e t I n t e g r a l a ( ) , d i n . getEps ( ) ) ;
}

19
20
21
22

@After
public void a f i s a r e ( ) {
System . out . p r i n t l n ( \ n I n d i c a t o r u l de r a s p u n s : +dout . g e t I n d ( ) ) ;
System . out . p r i n t f ( I n t e g r a l a : %16.8 f \n , dout . g e t I n t e g r a l a ( ) ) ;
System . out . p r i n t l n ( Numarul i t e r a t i i l o r e f e c t u a t e : +dout . g e t N i ( ) ) ;
}

24
25
26
27
28
29

public s t a t i c void main ( S t r i n g [ ] a r g s ) {


o r g . j u n i t . r u n n e r . JUnitCore . main ( T e s t I n t e g r a l a ) ;
}

31
32
33
34

org . j u n i t . ;
static org . j u n i t . Assert . ;
mathlib . c l i e n t . cvadra . ;
m a t h l i b . c l i e n t . c v a d r a . impl . ;

Rezultatele obtinute sunt


Indicatorul de raspuns : 0
Integrala :
0.27219826
Numarul iteratiilor efectuate : 1
Time: 0.1
OK (1 test)

1.7

Dezvoltarea mini-bibliotecii cu apache-maven

Aratam o modalitate de dezvoltare a mini-bibliotecii mathlib prin apache-maven.


Deoarece un proiect maven produce o singura iesire, este nevoie de 4 proiecte maven: doua
corespunzatoare celor doua interfete (cu iesirile mathlib.client.ecalg, mathlib.client.cvadra)
si alte doua pentru implementarea lor (cu iesirile mathlib.client.ecalg.impl, mathlib.client.
cvadra.impl ).
Clasele dezvoltate n 1.4 se utilizeaza nemodificate.
In prealabil arhivele jep-2.4.1.jar si matheclipse-parser-0.0.10.jar pe care le utilizam
trebuie depuse n depozitul local

1.7. DEZVOLTAREA MINI-BIBLIOTECII CU APACHE-MAVEN

37

set HOME=locatia_curenta
start mvn install:install-file
-Dfile=%HOME%\jep-2.4.1.jar
-DgroupId=jep
-DartifactId=jep
-Dversion=2.4.1
-Dpackaging=jar
start mvn install:install-file
-Dfile=%HOME%\matheclipse-parser-0.0.10.jar
-DgroupId=org.matheclipse
-DartifactId=matheclipse-parser
-Dversion=0.0.10
-Dpackaging=jar

Proiectul interfatei pentru rezolvarea unei ecuatii algebrice se genereaza prin


set GroupId=mathlib.client.ecalg
set ArtifactId=iecalg
set Version=1.0
set ArchetypeArtifactId=maven-archetype-quickstart
mvn -B archetype:generate
-DgroupId=%GroupId%
-DartifactId=%ArtifactId%
-Dversion=%Version%
-DarchetypeArtifactId=%ArchetypeArtifactId%

Dupa inserarea fisierelor java, desfasurarea aplicatiei devine


iecalg
|--> src
|
|--> main
|
|
|-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pom.xml

java
|-->
|
|
|
|
|

mathlib
|--> client
|
|--> ecalg
|
|
|
DataIn.java
|
|
|
DataOut.java
|
|
|
IMetodaTangentei.java

Prelucrarile necesare sunt: mvn clean install care nglobeaza stergerea fisierelor generate anterior de maven, compilarea, arhivarea si depunerea proiectului n depozitul local
maven.
Generam proiectul pentru implementarea interfetei definita mai sus.
set GroupId=mathlib.client.ecalg.impl
set ArtifactId=ecalgimpl
set Version=1.0
set ArchetypeArtifactId=maven-archetype-quickstart
mvn -B archetype:generate
-DgroupId=%GroupId%
-DartifactId=%ArtifactId%
-Dversion=%Version%
-DarchetypeArtifactId=%ArchetypeArtifactId%

Partea de test se completeaza cu clasele utilizate n 1.5 pentru calculul solutiei negative
a ecuatiei 2x x2 = 0. In final, desfasurarea proiectului este
ecalgimpl
|--> src
|
|-->
|
|
|
|
|
|
|
|

main
|-->
|
|
|

java
|--> mathlib
|
|--> client
|
|
|--> ecalg

38

|
|
|
|
|
|
|
|
|
|
|

CAPITOLUL 1. APLICAT
II NUMERICE SIMPLE

|
|
|
|
|--> test
|
|-->
|
|
|
|
|
|
|
|
|
|
|
|
pom.xml

|
|

|
|

|
|

|--> impl
|
|
MetodaTangentei.java

java
|-->
|
|
|
|
|

mathlib
|--> client
|
|--> ecalg
|
|
|--> impl
|
|
|
SimpluEcAlgDataIn.java
|
|
|
TestEcAlg.java

Fisierul pom.xml trebuie completat cu dependinta pentru iecalg. Codul fisierului pom.xml
devine
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

<p r o j e c t xmlns= h t t p : //maven . apache . o r g /POM/ 4 . 0 . 0


x m l n s : x s i= h t t p : //www. w3 . o r g /2001/XMLSchemai n s t a n c e
x s i : s c h e m a L o c a t i o n= h t t p : //maven . apache . o r g /POM/ 4 . 0 . 0
h t t p : //maven . apache . o r g /mavenv 4 0 0 . xsd >
<m o d e l V e r s i o n> 4 . 0 . 0</ m o d e l V e r s i o n>
<g r o u p I d>m a t h l i b . c l i e n t . e c a l g . impl</ g r o u p I d>
< a r t i f a c t I d>e c a l g i m p l</ a r t i f a c t I d>
<p a c k a g i n g>j a r</ p a c k a g i n g>
<version>1 . 0</ version>
<name>e c a l g i m p l</name>
<u r l>h t t p : //maven . apache . o r g</ u r l>
<d e p e n d e n c i e s>
<dependency>
<g r o u p I d>j u n i t</ g r o u p I d>
< a r t i f a c t I d>j u n i t</ a r t i f a c t I d>
<version>4 . 1 2</ version>
<s c o p e> t e s t</ s c o p e>
</ dependency>
<dependency>
<g r o u p I d>m a t h l i b . c l i e n t . e c a l g</ g r o u p I d>
< a r t i f a c t I d> i e c a l g</ a r t i f a c t I d>
<version>1 . 0</ version>
</ dependency>
</ d e p e n d e n c i e s>
</ p r o j e c t>

Se pot face urmatoarele prelucrari: mvn clean test


Partea referitoare la formula de integrare numerica se trateaza analog.
Odata dezvoltate, cele 4 proiecte pot fi asamblate ntr-un singur proiect maven, avand
structura
mathlib
|--> iecalg
|
|--> . . .
|--> ecalgimpl
|
|--> . . .
|--> icvadra
|
|--> . . .
|--> cvadraimpl
|
|--> . . .
|
pom.xml

cu fisierul pom.xml
1
2
3
4
5
7

<?xml version= 1 . 0 e n c o d i n g=UTF8 ?>


<p r o j e c t xmlns= h t t p : //maven . apache . o r g /POM/ 4 . 0 . 0
x m l n s : x s i= h t t p : //www. w3 . o r g /2001/XMLSchemai n s t a n c e
x s i : s c h e m a L o c a t i o n= h t t p : //maven . apache . o r g /POM/ 4 . 0 . 0
h t t p : //maven . apache . o r g /mavenv 4 0 0 . xsd >
<m o d e l V e r s i o n> 4 . 0 . 0</ m o d e l V e r s i o n>

1.8. UTILIZARE PRIN OSGI

8
9
10
11
12
14
15
16
17
18
19
20

39

<name> Maven m a t h l i b </name>


<g r o u p I d>m a t h l i b</ g r o u p I d>
<version>1 . 0</ version>
< a r t i f a c t I d>m a t h l i b</ a r t i f a c t I d>
<p a c k a g i n g>pom</ p a c k a g i n g>
<modules>
<module> i e c a l g</ module>
<module>e c a l g i m p l</ module>
<module>i c v a d r a</ module>
<module>c v a d r a i m p l</ module>
</ modules>
</ p r o j e c t>

Oricare din comenzile maven va actiona asupra fiecarui modul (modulul este denumirea
data unui proiect inclus).
Compilarea si testarea se obtine cu comanda mvn clean test.
Compilarea, testarea, arhivarea si copierea n depozitul local se obtine cu comanda
mvn clean install.

1.8

Utilizare prin OSGi

OSGi - Open Sourse Gateway initiative, 1999, (semnificatia numelui fiind astazi depasita) a dezvoltat un model de cadru de lucru privind:
gestiunea ciclului de viata a unei aplicatii (application life cycle management);
registru de servicii;
mediu de executie;
module.
Pe aceasta baza au fost dezvoltate interfete de programare (API), servicii, extensii OSGi
(OSGi layers).
Cadrul de lucru contine un model specific de aplicatie sub forma de componenta sau
modul OSGi (bundle for deployment). O asemenea componenta poate pune la dispozitia
altor componente functionalitati, comportandu-se ca un serviciu (ofertant de servicii) sau
poate executa o actiune punctuala. O componenta OSGi se prezinta sub forma unei arhive
jar.
In esenta, scopul unui cadru de lucru OSGi este oferirea unui mediu pentru crearea si
integrarea uniforma de unitati (module, componente) de soft.
O componenta OSGi se poate instala, lansa n executie, opri, actualiza si dezinstala.
Cadrul de lucru contine un registru de servicii care permite unei componente OSGi
sa sesizeze existenta, aparitia sau disparitia unor servicii.
Programarea unei aplicatii (serviciu) OSGi se poate face n mod
imperativ prin existenta unei clase activator ce implementeaza interfata org.osgi.
framework.BundleActivator.

40

CAPITOLUL 1. APLICAT
II NUMERICE SIMPLE

declarativ prin utilizarea unor resurse OSGi suplimentare care nlocuiesc activatorul
cu fisiere de configurare. Descriptive service, blueprint, iPOJO sunt tehnologii de
programare declarative.

Cadre de lucru OSGi


Exista mai multe implementari a modelului OSGi, dintre care amintim apache-felix,
apache-karaf, equinox din eclipse, Knopflerfish. Serverul de aplicatii glassfish nglobeaza
apache-felix.
Exemplificarea noastra se bazeaza pe apache-felix.

OSGi prin apache-felix


Instalarea consta n dezarhivarea arhivei descarcate din Internet.
Utilizare. Din catalogul unde s-a instalat apache-felix, mediul se lanseaza prin
java -jar bin\felix.jar
In catalogul n care s-a instalat apache-felix se va crea un subcatalog felix-cache care
este folosit de cadrul de lucru.
Comenzile OSGi sunt:
Comanda
lb
exit <int>
install file:modulOSGi .jar

Functionalitatea
Afiseaza lista modulelor OSGi instalate.
Paraseste si nchide cadrul de lucru.
Instaleaza modulul OSGi
La instalare unui modul i se atribuie n
vederea identificarii un numar natural id.
start id
Lanseaza modulul OSGi id.
start file: modulOSGi .jar
Instaleaza si lanseaza modulul OSGi
stop id
Opreste modulul OSGi id.
uninstall id
Dezinstaleaza modulul OSGi id.
Interfata de lucru, Apache Felix Gogo, implementeaza RFC (Request for Comments)
147 publicat de Internet Engineering Task Force (IETF).

Modelul de programare imperativ


Elementul cu care opereaza cadrul de lucru OSGi este modulul sau componenta OSGi
(bundle). In modelul de programare imperativ un modul OSGi este compus din
1. O clasa ce implementeaza interfata BundleActivator.
Interfata BundleActivator declara metodele
public void start(BundleContext ctx )
Fixeaza activitatile executate la lansarea modulului OSGi.

41

1.8. UTILIZARE PRIN OSGI

public void stop(BundleContext ctx )


Fixeaza activitatile executate la oprirea modulului OSGi.
Aceasta clasa poate lipsi n cazul declararii unei interfate.
2. Un fisier text manifest.mf de proprietati (nume: valoare) ale modulului OSGi, cu
extensia mf. Dintre proprietati mentionam:
Bundle-Name:

numele componentei OSGi

Bundele-Description:
Bundle-Version:

descrierea componentei OSGi

1.0.0

Bundle-Activator:
BundleActivator

clasa care implementeaza interfata

Bundle-Classpath: variabila classpath utilizata de componenta OSGi. Uzual,


primul element, indicat prin . (punct) va desemna catalogul curent.
Import-Package:
OSGi.

Lista pachetelor utilizate, furnizate de alte componente

Export-Package: Lista pachetelor cuprinse n modulul OSGi.


Fiecarui pachet trebuie sa i se atribuie o versiune, de exemplu
Export-Package: mathlib.client.cvadra;version="1.0.0",mathlib.client.ecalg;
version="1.0.0"

Ultima linie din fisierul manifest.mf este o linie vida. In liste, separatorul este
virgula.

Rezolvarea problemelor prin module OSGi


Consideram clasa TestEcAlg
1
2
3
5
6
7
8
9
10
11
12
13
14

import m a t h l i b . c l i e n t . e c a l g . ;
import m a t h l i b . c l i e n t . e c a l g . impl . ;
import o r g . o s g i . framework . ;
public c l a s s A c t i v a t o r implements B u n d l e A c t i v a t o r {
public void s t a r t ( BundleContext c o n t e x t ) {
DataIn d i n=new SimpluEcAlgDataIn ( ) ;
IMetodaTangentei o b j=new MetodaTangentei ( ) ;
DataOut dout=o b j . metodaTangentei ( d i n ) ;
System . out . p r i n t l n ( \ n I n d i c a t o r u l de r a s p u n s : +dout . g e t I n d ( ) ) ;
System . out . p r i n t l n ( S o l u t i a e c u a t i e i : +dout . getX ( ) ) ;
System . out . p r i n t l n ( V a l o a r e a f u n c t i e i i n s o l u t i e : +dout . getF ( ) ) ;
System . out . p r i n t l n ( Numarul i t e r a t i i l o r e f e c t u a t e : +dout . g e t N i ( ) ) ;
}
public void s t o p ( BundleContext c o n t e x t ) {}

16
17

si dupa compilare, arhivam cu jar cfvm testecalg.jar manifest.mf ... ansamblul


|-->
|
|
|

lib
|
mathlib.jar
Activator.class
SimpluEcAlgDataIn.class

42

CAPITOLUL 1. APLICAT
II NUMERICE SIMPLE

Fisierul manifest.mf este


1
2
3
4
5
6

BundleName : TestEcAlg
BundleD e s c r i p t i o n : Test EcAlg
BundleV e r s i o n : 1 . 0 . 0
BundleA c t i v a t o r : A c t i v a t o r
BundleC l a s s p a t h : . , l i b / m a t h l i b . j a r
ImportPackage : o r g . o s g i . framework

Dupa lansarea cadrului OSGi n executie, instalam componenta OSGi astfel creata si o
lansam n lucru:
g! start file: . . .\testecalg.jar
Indicatorul de raspuns : 0
Solutia ecuatiei : -0.766664695962095
Valoarea functiei in solutie : 1.1102230246251565E-16
Numarul iteratiilor efectuate : 5

Pentru a relua executia trebuie sa aflam codul atribuit de cadrul de lucru OSGi componentei testecalg.jar
g! lb
ID|State
. . .
5|Active

|Level|Name
|

1|TestEcAlg(1.0.0)|1.0.0

dupa care componenta trebuie oprita


g! stop 5

Dezinstalarea componentei de cadrul de lucru OSGi se obtine prin


g! uninstall 5

O alta varianta de programare consta n utilizarea serviciilor OSGi. In cele ce urmeaza


vom pleca de la mini-biblioteca mathlib realizata si arhivata n fisierul mathlib.jar.
Se va crea o componenta OSGi care va nregistra cate un serviciu pentru fiecare
interfeta IMetodaTangentei si IMetodaSimpson. Totodata, componenta OSGi, corespunzatoare interfetelor, va exporta pachetele
mathlib.client.cvadra;version=1.0.0,mathlib.client. ecalg;version=1.0.0.
Inregistrarea unui serviciu se face prin intermediul metodei
ServiceRegistration registerService(String, Object, Properties)
a clasei BundleContext, unde corespunzator variabilei de tip
String se afla numele interfetei, care fixeaza astfel numele serviciului;
Object se afla o instanta a clasei care implementeaza interfata;
Properties se afla elemente pentru identificarea serviciului, n cazul n care mai
multe componente OSGi genereaza servicii aceleiasi interfete.
In cazul exemplului, codul clasei Activator.java este

1.8. UTILIZARE PRIN OSGI

1
2
3
4
5
7
8
9
10
11
12
13
14
15
16
17
18
19

import
import
import
import
import

c l i e n t . cvadra . ;
client . ecalg . ;
c l i e n t . c v a d r a . impl . ;
c l i e n t . e c a l g . impl . ;
. framework . ;

public c l a s s A c t i v a t o r implements B u n d l e A c t i v a t o r {
S e r v i c e R e g i s t r a t i o n metodaSimpsonService ;
S e r v i c e R e g i s t r a t i o n metodaTangenteiService ;
public void s t a r t ( BundleContext c o n t e x t ) {
m e t o d a S i m p s o n S e r v i c e=
c o n t e x t . r e g i s t e r S e r v i c e ( IMetodaSimpson . c l a s s . getName ( ) ,
new MetodaSimpson ( ) , n u l l ) ;
System . out . p r i n t l n ( R e g i s t e r i n g MetodaSimpson s e r v i c e . ) ;
m e t o d a T a n g e n t e i S e r v i c e=
c o n t e x t . r e g i s t e r S e r v i c e ( IMetodaTangentei . c l a s s . getName ( ) ,
new MetodaTangentei ( ) , n u l l ) ;
System . out . p r i n t l n ( R e g i s t e r i n g MetodaTangentei s e r v i c e . ) ;
}
public void s t o p ( BundleContext c o n t e x t ) {
metodaSimpsonService . u n r e g i s t e r ( ) ;
metodaTangenteiService . u n r e g i s t e r ( ) ;
}

21
22
23
24
25

mathlib .
mathlib .
mathlib .
mathlib .
org . o s g i

43

iar fisierul manifest.mf este


1
2
3
4
5
6
7
8

BundleName : M a t h l i b S e r v i c e
BundleD e s c r i p t i o n : Mathlib S e r v i c e
BundleV e r s i o n : 1 . 0 . 0
BundleA c t i v a t o r : A c t i v a t o r
BundleC l a s s p a t h : . , l i b / m a t h l i b . j a r , l i b / l o g 4 j 1 . 2 . 1 5 . j a r
ImportPackage : o r g . o s g i . framework
ExportPackage : m a t h l i b . c l i e n t . c v a d r a ; v e r s i o n= 1 . 0 . 0 ,
m a t h l i b . c l i e n t . e c a l g ; v e r s i o n= 1 . 0 . 0

Desfasurarea resurselor n vederea arhivarii este


|--> lib
|
|
mathlib.jar
|
Activator.class

Rezolvarea fiecarei probleme se obtine n cate un modul OSGi. Vom reutiliza clasele
SimpleEcAlgDataIn si SimpluCvadraDataIn, la care se adauga cate o clasa care implementeaza interfata BundleActivator.
Calculul solutiei negative a ecuatiei 2x x2 = 0
Un obiect care implementeaza interfata se obtine n doi pasi:
1. Se gaseste o referinta a serviciului cu metoda
ServiceReference getServiceReference(String)
a clasei BundleContext. Variabila String reprezinta numele serviciului, adica numele interfetei.
2. Se obtine o instanta a clasei ce implementeaza interfata cu metoda
Object getService(ServiceReference)

44

CAPITOLUL 1. APLICAT
II NUMERICE SIMPLE

Codul clasei Activator.java este


1
2
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

import m a t h l i b . c l i e n t . e c a l g . ;
import o r g . o s g i . framework . ;
public c l a s s A c t i v a t o r implements B u n d l e A c t i v a t o r {
ServiceReference metodaSimpsonServiceReference ;
public void s t a r t ( BundleContext c o n t e x t ) {
try {
m e t o d a S i m p s o n S e r v i c e R e f e r e n c e=
c o n t e x t . g e t S e r v i c e R e f e r e n c e ( IMetodaTangentei . c l a s s . getName ( ) ) ;
i f ( m e t o d a S i m p s o n S e r v i c e R e f e r e n c e != n u l l ) {
DataIn d i n=new SimpluEcAlgDataIn ( ) ;
IMetodaTangentei o b j=
( IMetodaTangentei ) c o n t e x t . g e t S e r v i c e ( m e t o d a S i m p s o n S e r v i c e R e f e r e n c e ) ;
DataOut dout=o b j . metodaTangentei ( d i n ) ;
System . out . p r i n t l n ( \ n I n d i c a t o r u l de r a s p u n s : +dout . g e t I n d ( ) ) ;
System . out . p r i n t l n ( S o l u t i a e c u a t i e i : +dout . getX ( ) ) ;
System . out . p r i n t l n ( V a l o a r e a f u n c t i e i i n s o l u t i e : +dout . getF ( ) ) ;
System . out . p r i n t l n ( Numarul i t e r a t i i l o r e f e c t u a t e : +dout . g e t N i ( ) ) ;
}
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( App E x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;
}
}
public void s t o p ( BundleContext c o n t e x t ) {
i f ( m e t o d a S i m p s o n S e r v i c e R e f e r e n c e != n u l l ) {
context . ungetService ( metodaSimpsonServiceReference ) ;
}
}

26
27
28
29
30
31

Fisierul manifest.mf corespunzator este


1
2
3
4
5

BundleName : AppEcAlg
BundleD e s c r i p t i o n : R e z o l v a r e a u n e i e c u a t i i a l g e b r i c e
BundleV e r s i o n : 1 . 0 . 0
BundleA c t i v a t o r : A c t i v a t o r
ImportPackage : o r g . o s g i . framework , m a t h l i b . c l i e n t . e c a l g

Daca service.jar si appecalg.jar sunt arhivele corespunzatoare componentelor OSGi


MathlibService si respectiv AppEcAlg (dupa valoarea atributului Bundle-Name) atunci
comenzile OSGi pentru rularea aplicatiei sunt
g! start file: . . .\service.jar
Registering MetodaSimpson service.
Registering MetodaTangentei service.
g! start file: . . .\appecalg.jar

Calculul integralei

R
4

ln(1 + tan x)dx

In mod asemanator, dar folosind alta modalitate de programare OSGi, utilizam


Clasa Activator.java
1
2
3
5
6
7

import m a t h l i b . c l i e n t . c v a d r a . ;
import o r g . o s g i . framework . ;
import o r g . o s g i . u t i l . t r a c k e r . S e r v i c e T r a c k e r ;
public c l a s s A c t i v a t o r implements B u n d l e A c t i v a t o r {
ServiceTracker metodaSimpsonServiceTracker ;
public void s t a r t ( BundleContext c o n t e x t ) {

1.8. UTILIZARE PRIN OSGI

m e t o d a S i m p s o n S e r v i c e T r a c k e r=new S e r v i c e T r a c k e r ( c o n t e x t ,
IMetodaSimpson . c l a s s . getName ( ) , n u l l ) ;
m e t o d a S i m p s o n S e r v i c e T r a c k e r . open ( ) ;
DataIn d i n=new SimpluCvadraDataIn ( ) ;
IMetodaSimpson o b j=
( IMetodaSimpson ) m e t o d a S i m p s o n S e r v i c e T r a c k e r . g e t S e r v i c e ( ) ;
DataOut dout=o b j . metodaSimpson ( d i n ) ;
System . out . p r i n t l n ( \ n I n d i c a t o r u l de r a s p u n s : +dout . g e t I n d ( ) ) ;
System . out . p r i n t l n ( I n t e g r a l a : +dout . g e t I n t e g r a l a ( ) ) ;
System . out . p r i n t l n ( Numarul i t e r a t i i l o r e f e c t u a t e : +dout . g e t N i ( ) ) ;

8
9
10
11
12
13
14
15
16
17
18

20

public void s t o p ( BundleContext c o n t e x t ) {


metodaSimpsonServiceTracker . c l o s e ( ) ;
}

21
22
23

mpreuna cu manifest.mf
1
2
3
4
5
6

BundleName : A p p I n t e g r a l a
BundleD e s c r i p t i o n : C a l c u l u l u n e i i n t e g r a l e
BundleV e r s i o n : 1 . 0 . 0
BundleA c t i v a t o r : A c t i v a t o r
ImportPackage : o r g . o s g i . framework , o r g . o s g i . u t i l . t r a c k e r ,
mathlib . c l i e n t . cvadra

45

46

CAPITOLUL 1. APLICAT
II NUMERICE SIMPLE

Capitolul 2
Accesarea n Java a unor produse
matematice
Multe pachete de programe matematice ofera posibilitatea apelarii lor din clase Java.
Ne vom limita numai la produse distribuite gratuit. Vom prezenta utilizarea n Java a
produselor Mathematica, Maple, Scilab.
Ca motivatii pentru un asemenea interes este posibilitatea elaborarii unei aplicatii
Java care utilizeaza functionalitati ale softurilor amintite.

2.1

Java cu Mathematica

Mathematica este unul din produsele de varf de matematica cu facilitati de calcul


simbolic si numeric, de grafica si de dezvoltare - programare proprie. Mathematica este
un produs comercial realizat de Wolfram Research.
Legatura dintre Mathematica si Java este asigurata de componenta JLink a produsului. JLink permite utilizarea unei clase Java ntr-o sesiune Mathematica si a resurselor
Mathematica ntr-o clasa Java. Aceasta din urma posibilitate va fi prezentata n continuare.
Compilarea ca si executia presupune declararea n variabila classpath a fisierului
JLink.jar din distributia Mathematica.
Intr-o clasa Java, JLink se declara prin
import com.wolfram.jlink.*;
Accesarea resurselor Mathematica se face prin intermediul unui obiect de tip KernelLink,
a carei instantiere poate fi
KernelLink ml=null;
try{
String[] mlArgs = {"-linkmode", "launch", "-linkname", args[0]};
ml=MathLinkFactory.createKernelLink(mlArgs);
ml.discardAnswer();
}
47

48

CAPITOLUL 2. ACCESAREA IN JAVA A UNOR PRODUSE MATEMATICE

catch(MathLinkException e){
System.out.println("Fatal opening link error : "+e.getMessage());
System.exit(1);
}
Ultimul element al sirului mlArgs fixeaza locatia nucleului MathKernel.exe, fiind transmis
ca argument al programului Java.
Sablonul de prelucrare al unei expresii / comenzi Mathematica este
try{
// Evaluarea expresiei / comenzii reprezentata prin String-ul expr
String expr=". . .";
ml.evaluate(expr);
ml.waitForAnswer();
// Prelucrarea rezultatului
}
catch(MathLinkException e){
System.out.println("MathLinkException : "+e.getMessage());
}
finally{
ml.close();
}
Alternativ, metoda evaluate poate avea ca parametru o variabila de tip Expr.
Functie de tipul rezultatului, acesta se obtine cu una din metodele clasei KernerLink:
Expr getExpr(), double getDouble(), int getInteger(), boolean getBoolean().
Exemplul 2.1.1 Sa se rezolve ecuatia 2x x2 = 0.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

import com . wolfram . j l i n k . ;


public c l a s s NSolve {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
K e r n e l L i n k ml=n u l l ;
try {
S t r i n g [ ] mlArgs = { linkmode , l a u n c h , linkname , a r g s [ 0 ] } ;
ml = MathLinkFactory . c r e a t e K e r n e l L i n k ( mlArgs ) ;
}
catch ( MathLinkException e ) {
System . out . p r i n t l n ( F a t a l o p e n i n g l i n k e r r o r : +e . g e t M e s s a g e ( ) ) ;
System . e x i t ( 1 ) ;
}
try {
ml . d i s c a r d A n s w e r ( ) ; // f . i m p o r t a n t
ml . e v a l u a t e ( NSolve [ 2 xx2==0,x ] ) ;
ml . waitForAnswer ( ) ;
Expr r e s u l t=ml . getExpr ( ) ;
System . out . p r i n t l n ( r e s u l t . t o S t r i n g ( ) ) ;
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( MathLinkException : +e . g e t M e s s a g e ( ) ) ;
}
finally {
ml . c l o s e ( ) ;
}
}
}

2.1. JAVA CU MATHEMATICA

49

Executia se comanda prin


java NSolve "d:/Wolfram Research/Mathematica/5.1/MathKernel.exe"

iar rezultatul obtinut este


{{Rule[x,-0.766664695962123]},{Rule[x,2.0]},{Rule[x,4.0]}}
Extragerea solutiilor se poate programa utilizand metodele clasei Expr, prin
for(int i=1;i<=result.length();i++){
Expr e1=result.part(i);
Expr e2=e1.part(1);
Expr[] e3=e2.args();
System.out.println(e3[1].toString());
}

Vizualizarea imaginilor grafice produse de Mathematica se face prin intermediul obiectelor


care instantiaza clasele:
MathGraphicsJPanel,
ce extinde clasa javax.swing.JFrame;
MathCanvas
ce extinde clasa java.awt.Canvas.
Ambele clase contin metodele:
void setImageType(int type)
Fixeaza natura raspunsului GRAPHICS sau TYPESET.
void setUsesFE(boolean useFE )
Fixeaza modul de realizare a imaginii pe ecran, cu Mathematica sau nu.
void setMathCommand(String cmd )
Fixeaza functia Mathematica care se evalueaza si a carui rezultat se afiseaza.
Image getImage()
Returneaza imaginea grafica construita ntr-o variabila de tip Image.
Exemplul 2.1.2 Program Java care afiseaza reprezentarile grafice realizate de Mathematica.
Utilizand pachetul javax.swing, codul sursa este
1

import com . wolfram . j l i n k . ;

public c l a s s MathGraphics extends MathJFrame{


private MathGraphicsJPanel mathGraphicsJPanel ;
private j a v a x . swing . J L a b e l mJLabel ;
private j a v a x . swing . JTextArea mJTextArea ;
private j a v a x . swing . JButton mJButton ;
private j a v a x . swing . J S c r o l l P a n e m J S c r o l l P a n e ;

4
5
6
7
8

50

CAPITOLUL 2. ACCESAREA IN JAVA A UNOR PRODUSE MATEMATICE

10

s t a t i c K e r n e l L i n k ml ;

12

public MathGraphics ( ) {
initComponents ( ) ;
}

13
14
16
17
18
19
20

private void i n i t C o m p o n e n t s ( ) {
j a v a . awt . G r i d B a g C o n s t r a i n t s g r i d B a g C o n s t r a i n t s ;
s e t T i t l e ( Mathematica : G r a f i c a ) ;
setSize (400 ,400);
getContentPane ( ) . s e t L a y o u t (new j a v a . awt . GridBagLayout ( ) ) ;
mathGraphicsJPanel=new MathGraphicsJPanel ( ml ) ;
mathGraphicsJPanel . s e t B a c k g r o u n d ( j a v a . awt . C o l o r . w h i t e ) ;
mathGraphicsJPanel . s e t P r e f e r r e d S i z e (new j a v a . awt . Dimension ( 2 5 0 , 2 0 0 ) ) ;
g r i d B a g C o n s t r a i n t s = new j a v a . awt . G r i d B a g C o n s t r a i n t s ( ) ;
gridBagConstraints . gridx = 1;
gridBagConstraints . gridy = 0;
getContentPane ( ) . add ( mathGraphicsJPanel , g r i d B a g C o n s t r a i n t s ) ;

22
23
24
25
26
27
28

mJLabel=new j a v a x . swing . J L a b e l ( ) ;
mJLabel . s e t P r e f e r r e d S i z e (new j a v a . awt . Dimension ( 2 0 0 , 1 8 ) ) ;
mJLabel . s e t T e x t ( E x p r e s i e \ Mathematica \ ) ;
mJLabel . s e t H o r i z o n t a l A l i g n m e n t ( j a v a x . swing . SwingConstants .CENTER) ;
g r i d B a g C o n s t r a i n t s = new j a v a . awt . G r i d B a g C o n s t r a i n t s ( ) ;
gridBagConstraints . gridx = 0;
gridBagConstraints . gridy = 0;
getContentPane ( ) . add ( mJLabel , g r i d B a g C o n s t r a i n t s ) ;

30
31
32
33
34
35
36
37

m J S c r o l l P a n e=new j a v a x . swing . J S c r o l l P a n e ( ) ;
m J S c r o l l P a n e . s e t P r e f e r r e d S i z e (new j a v a . awt . Dimension ( 2 0 0 , 6 0 ) ) ;
mJTextArea=new j a v a x . swing . JTextArea ( ) ;
m J S c r o l l P a n e . s e t V i e w p o r t V i e w ( mJTextArea ) ;
g r i d B a g C o n s t r a i n t s = new j a v a . awt . G r i d B a g C o n s t r a i n t s ( ) ;
gridBagConstraints . gridx = 0;
gridBagConstraints . gridy = 1;
getContentPane ( ) . add ( mJScrollPane , g r i d B a g C o n s t r a i n t s ) ;

39
40
41
42
43
44
45
46

mJButton=new j a v a x . swing . JButton ( ) ;


mJButton . s e t T e x t ( E v a l u e a z a ) ;
mJButton . s e t P r e f e r r e d S i z e (new j a v a . awt . Dimension ( 1 2 0 , 1 8 ) ) ;
mJButton . a d d M o u s e L i s t e n e r (new j a v a . awt . e v e n t . MouseAdapter ( ) {
public void m o u s e Cl i c k e d ( j a v a . awt . e v e n t . MouseEvent e v t ) {
mJButtonMouseClicked ( e v t ) ;
}
});
g r i d B a g C o n s t r a i n t s = new j a v a . awt . G r i d B a g C o n s t r a i n t s ( ) ;
gridBagConstraints . gridx = 0;
gridBagConstraints . gridy = 2;
getContentPane ( ) . add ( mJButton , g r i d B a g C o n s t r a i n t s ) ;

48
49
50
51
52
53
54
55
56
57
58
59

addWindowListener (new j a v a . awt . e v e n t . WindowAdapter ( ) {


public void windowClosing ( j a v a . awt . e v e n t . WindowEvent e v t ) {
i f ( ml!= n u l l ) {
ml . evaluateToInputForm ( CloseFrontEnd [ ] , 0 ) ;
ml . c l o s e ( ) ;
}
dispose ( ) ;
System . e x i t ( 0 ) ;
}
});
ml . evaluateToInputForm ( Needs [ \ +K e r n e l L i n k .PACKAGE CONTEXT+ \ ] , 0 ) ;
ml . evaluateToInputForm ( ConnectToFrontEnd [ ] , 0 ) ;
toFront ( ) ;
pack ( ) ;

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

2.2. JAVA CU MAPLE

private void mJButtonMouseClicked ( j a v a . awt . e v e n t . MouseEvent e v t ) {


mathGraphicsJPanel . setImageType ( MathGraphicsJPanel . GRAPHICS ) ;
mathGraphicsJPanel . setUsesFE ( true ) ;
mathGraphicsJPanel . setMathCommand ( mJTextArea . g e t T e x t ( ) ) ;
}

77
78
79
80
81

public s t a t i c void main ( S t r i n g a r g s [ ] ) {


try {
S t r i n g [ ] mlArgs = { linkmode , l a u n c h , linkname , a r g s [ 0 ] } ;
ml = MathLinkFactory . c r e a t e K e r n e l L i n k ( mlArgs ) ;
ml . d i s c a r d A n s w e r ( ) ;
}
catch ( MathLinkException e ) {
System . out . p r i n t l n ( An e r r o r o c c u r r e d c o n n e c t i n g t o t h e k e r n e l . ) ;
i f ( ml != n u l l )
ml . c l o s e ( ) ;
return ;
}
j a v a . awt . EventQueue . i n v o k e L a t e r (new Runnable ( ) {
public void run ( ) {
new MathGraphics ( ) . s e t V i s i b l e ( true ) ;
}
});
}

83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

51

Clientul interactioneaza cu programul prin interfata grafica din Fig. 2.1. In zona
TextArea se introduce o comanda Mathematica.

Fig. 2.1: Reprezentare grafica produsa de Mathematica.

2.2

Java cu Maple

Maple este un produs comercial de matematica produs de Waterloo Maple Inc., aflat
n concurenta cu Mathematica.

52

CAPITOLUL 2. ACCESAREA IN JAVA A UNOR PRODUSE MATEMATICE

Legatura dintre Java si Maple se stabileste prin interfata de programare (Application


Program Interface API) openmaple. Problema de care ne ocupam consta n utilizarea
facilitatilor oferite de Maple n programe Java.
Utilizarea lui openmaple ntr-un program Java se declara prin
import com.maplesoft.openmaple.*;
import com.maplesoft.externalcall.MapleException;
Principala clasa prin care un program Java interactioneaza cu Maple este
com.maplesoft.openmaple.Engine
Constructorul clasei este
Engine(String[] args, EngineCallBack cb, Object userData, Object res)
unde
args={java};
cb este o instanta a unei clase ce implementeaza interfata EngineCallBack. Interfata
declara metode care fixeaza raspunsurile la apelurile emise de nucleul Maple (apeluri
inverse);
openmath ofera clasa EngineCallBackDefault ca o implementare uzuala a interfetei
EngineCallBack. Orice mesaj / rezultat furnizat de Maple este afisat;
userData este un parametru care contine date ce se includ n cb la fiecare apel
invers;
res=null - este un argument neutilizat.
Dintre metodele clasei Engine amintim:
Algebraic evaluate(String comandaMaple)
Clasa Algebraic este o clasa acoperitoare n Java a obiectelor Maple.
Dintre metodele clasei Algebraic semnalam:
String toString()
Converteste obiectul Maple n string. Daca se aplica acestui string metoda evaluate
atunci se reobtine obiectul Maple.
Reluam exercitiul
Exemplul 2.2.1 Sa se rezolve ecuatia 2x x2 = 0.
Codul programului este

2.3. JAVA CU SCILAB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

53

import com . m a p l e s o f t . openmaple . ;


import com . m a p l e s o f t . e x t e r n a l c a l l . MapleException ;
class Solve {
public s t a t i c void main ( S t r i n g a r g s [ ] ) {
try {
S t r i n g [ ] argsMaple={ j a v a } ;
Engine e n g i n e=new Engine ( argsMaple , new E n g i n e C a l l B a c k s D e f a u l t ( ) ,
null , n u l l ) ;
A l g e b r a i c s o l=e n g i n e . e v a l u a t e ( u : = [ e v a l f ( s o l v e ( 2 xx 2 , x ) ) ] ; ) ;
A l g e b r a i c an=e n g i n e . e v a l u a t e ( nops ( u ) ; ) ;
i n t n=(new I n t e g e r ( an . t o S t r i n g ( ) ) ) . i n t V a l u e ( ) ;
double [ ] x=new double [ n ] ;
f o r ( i n t i =1; i <=n ; i ++){
A l g e b r a i c ax=e n g i n e . e v a l u a t e ( u [ +i+ ] ; ) ;
x [ i 1]=(new Double ( ax . t o S t r i n g ( ) ) ) . d o u b l e V a l u e ( ) ;
}
System . out . p r i n t l n ( S o l u t i i l e o b t i n u t e ) ;
f o r ( i n t i =0; i <n ; i ++)
System . out . p r i n t l n ( x [ +( i +1)+ ] = +x [ i ] ) ;
}
catch ( MapleException e ) {
System . out . p r i n t l n ( MapleException : +e . g e t M e s s a g e ( ) ) ;
return ;
}
}
}

cu rezultatele
u := [2., 4., -.7666646958]
3
2.
4.
-.7666646958
Solutiile obtinute
x[1] = 2.0
x[2] = 4.0
x[3] = -0.7666646958

Primele cinci linii sunt afisate de obiectul anonim de tip EngineCallBackDefault.


Soluta negativa se putea obtine direct prin
engine.evaluate("solve(2^x-x^2,x,x=-infinity..0);");

Semnalam faptul ca pentru compilare si executie trebuie sa includem n variabila de sistem classpath fisierele jopenmaple.jar, externalcall.jar din catalogul Maple HOME\java.
In plus, pentru executie, trebuie completata variabila de sistem PATH cu calea catre
catalogul Maple HOME\bin.X86 64 WINDOWS.

2.3

Java cu Scilab

Scilab este un produs de calcul numeric produs de INRIA (Institut National de Recherche en Informatique et Automatique) Franta disponibil n mediile Windows, Linux
si Mac OS X. Produsul este distribuit gratuit. Scilab este nsotit de o documentatie
cuprinzatoare.
Din punctul de vedere al utilizari Scilab are trasaturi comune cu produsul comercial
Matlab.

54

CAPITOLUL 2. ACCESAREA IN JAVA A UNOR PRODUSE MATEMATICE

Prezentarea se va rezuma la versiunea a doua a puntii oferita de Scilab catre Java.


Functiile Scilab pot fi apelate dintr-un program Java, conexiunea cu Java se bazeaza
pe pachetele
No. Resursa jar
Locatia
1
org.scilab.modules.javasci.jar SCILAB HOME\modules\javasci\jar
2
org.scilab.modules.types.jar
SCILAB HOME\modules\types\jar
Compilarea si executia necesita prezenta n variabila sistem classpath a referintei
catre fiserele jar mentionate mai sus.
Vom utiliza unele din clasele si interfetele:
org.scilab.modules.javasci.Scilab
org.scilab.modules.javasci.JavasciException
org.scilab.modules.types.ScilabType
org.scilab.modules.types.ScilabBoolean
org.scilab.modules.types.ScilabDouble
org.scilab.modules.types.ScilabInteger
org.scilab.modules.types.ScilabString
org.scilab.modules.types.ScilabList
Prezentam succint elementele care intervin n exemplele pe care le vom da:

Clasa org.scilab.modules.javasci.Scilab
Constructor:
public Scilab()
Clasa Scilab contine metodele statice:
public boolean open() throws JavasciException
public boolean close()
public boolean exec(String sarcina )
public boolean exec(String[] sarcini )
public boolean exec(File numeFisierScript)
public boolean put(String numeVar, ScilabType val )
Se defineste variabila Scilab numeVar a carei valoare este val.
ScilabType get(String numeVar )
Returneaza un obiect acoperitor Java corespunzator tipului variabilei Scilab.
Valoarea logica returnata de metodele de mai sus este true daca Scilab nu genereaza o
eroare.
Sablonul de apelare pentru executia de cod Scilab este

2.3. JAVA CU SCILAB

55

import org.scilab.modules.javasci.Scilab;
public class ApelScilab{
public static void main(String[] args){
try{
Scilab sci=new Scilab();
if(sci.open()){
. . .
sci.exec( cod Scilab );
. . .
sci.close();
}
else{
System.out.println("Could not start Scilab ");
}
}
catch(org.scilab.modules.javasci.JavasciException e) {
System.err.println("Exception: " + e.getLocalizedMessage());
}
}
}

Interfata org.scilab.modules.types.ScilabType
Interfata declara metodele:
boolean equals(Object obiect)
int getHeight()
Returneaza numarul liniilor.
int getWidth()
Returneaza numarul coloanelor.
boolean isEmpty()
String toString()
Interfata este implementata de clasele ScilabBoolean, ScilabDouble, ScilabInteger,
ScilabString, ScilabList.

Clasa org.scilab.modules.types.ScilabDouble
Constructori:
ScilabDouble()

56

CAPITOLUL 2. ACCESAREA IN JAVA A UNOR PRODUSE MATEMATICE

ScilabDouble(double data)
ScilabDouble(double[][] data)
ScilabDouble(double realData, double imagData)
ScilabDouble(double[][] realData, double[][] imagData)
Metode:
double[][] getRealPart()
double[][] getImaginarylPart()
boolean isReal()
Schema pentru transferul unei date double x din Java n Scilab consta din
double x=. . .;
ScilabDouble sci_x=new new ScilabDouble(x);
sci.put("x",sci_x);
Invers, preluarea n Java a valorii unei variabile Scilab a, presupusa numar real, se programeaza prin
ScilabDouble sci_a=(ScilabDouble)sci.get("a");
double[][] aa=sci_a.getRealPart();
double a=aa[0][0];
Exemplul 2.3.1 Executia unui script Scilab u=1,v=u+1, disp(v).
1
2
3
5
6
7
8
9

import o r g . s c i l a b . modules . j a v a s c i . S c i l a b ;
import o r g . s c i l a b . modules . t y p e s . S c i l a b T y p e ;
import o r g . s c i l a b . modules . t y p e s . S c i l a b D o u b l e ;
public c l a s s
TstJavaSci1 {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
try {
S c i l a b s c i=new S c i l a b ( ) ;
i f ( s c i . open ( ) ) {
s c i . e x e c (new S t r i n g [ ] { u=1 , v=u+1 , d i s p ( v ) } ) ;

11

sci . close ();


}
else {
System . out . p r i n t l n ( Could not s t a r t S c i l a b ) ;
}

13
14
15
16
17

}
catch ( o r g . s c i l a b . modules . j a v a s c i . J a v a s c i E x c e p t i o n e ) {
System . e r r . p r i n t l n ( An e x c e p t i o n o c c u r e d : + e . g e t L o c a l i z e d M e s s a g e ( ) ) ;
}

18
19
20
21

22
23

Se obtine

57

2.3. JAVA CU SCILAB

2.

Exemplul 2.3.2 Calculul solutiei negative a ecuatiei 2x x2 = 0.


1
2
3
5
6
7
8
9
10
11
12
13
14

import o r g . s c i l a b . modules . j a v a s c i . S c i l a b ;
import o r g . s c i l a b . modules . t y p e s . S c i l a b T y p e ;
import o r g . s c i l a b . modules . t y p e s . S c i l a b D o u b l e ;
public c l a s s
TstJavaSci2 {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
try {
S c i l a b s c i=new S c i l a b ( ) ;
i f ( s c i . open ( ) ) {
S t r i n g [ ] s={ d e f f ( \ y=f c t ( x ) \ , \ y =2.xx . x \ ) , [ x , y , i n f o ]= f s o l v e ( 0 . 5 , f c t ) } ;
s c i . exec ( s ) ;
S c i l a b D o u b l e s c i x =( S c i l a b D o u b l e ) s c i . g e t ( x ) ;
double [ ] [ ] x=s c i x . g e t R e a l P a r t ( ) ;
System . out . p r i n t l n ( S o l u t i a : +x [ 0 ] [ 0 ] ) ;
S c i l a b D o u b l e s c i y =( S c i l a b D o u b l e ) s c i . g e t ( y ) ;
double [ ] [ ] y=s c i y . g e t R e a l P a r t ( ) ;
System . out . p r i n t l n ( V a l o a r e a f u n c t i e i i n s o l u t i e : +y [ 0 ] [ 0 ] ) ;

16
17
18

S c i l a b D o u b l e s c i i n f o =( S c i l a b D o u b l e ) s c i . g e t ( i n f o ) ;
double [ ] [ ] i n f o= s c i i n f o . g e t R e a l P a r t ( ) ;
System . out . p r i n t l n ( I n d i c a t o r u l de r a s p u n s : +i n f o [ 0 ] [ 0 ] ) ;
sci . close ();

20
21
22
23

}
else {
System . out . p r i n t l n ( Could not s t a r t S c i l a b ) ;
}

24
25
26
27

}
catch ( o r g . s c i l a b . modules . j a v a s c i . J a v a s c i E x c e p t i o n e ) {
System . e r r . p r i n t l n ( An e x c e p t i o n o c c u r e d : + e . g e t L o c a l i z e d M e s s a g e ( ) ) ;
}

28
29
30
31

32
33

Rezultatele obtinute sunt


Solutia : -0.766664695962123
Valoarea functiei in solutie : 1.1102230246251565E-16
Indicatorul de raspuns : 1.0

Exemplul 2.3.3 Calculul integralei


1
2
3
5
6
7
8
9
10
11
12
13
14
15
16
17

R
4

ln(1 + tan x)dx.

import o r g . s c i l a b . modules . j a v a s c i . S c i l a b ;
import o r g . s c i l a b . modules . t y p e s . S c i l a b T y p e ;
import o r g . s c i l a b . modules . t y p e s . S c i l a b D o u b l e ;
public c l a s s
TstJavaSci3 {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
try {
S c i l a b s c i=new S c i l a b ( ) ;
i f ( s c i . open ( ) ) {
S t r i n g f c t= \ l o g (1+ tan ( x ) ) \ ;
S t r i n g v a r= \ x \ ;
S t r i n g lowerBound= 0 ;
S t r i n g upperBound=%p i /4 ;
S t r i n g scicomm=u=i n t e g r a t e ( +f c t+ , +v a r+ , +lowerBound+ , +upperBound+ ) ;
boolean e r r o r=s c i . e x e c ( scicomm ) ;
System . out . p r i n t l n ( O p e r a t i a sa t e r m i n a t cu s u c c e s ( t r u e / f a l s e ) : +e r r o r ) ;
S c i l a b D o u b l e s c i u =( S c i l a b D o u b l e ) s c i . g e t ( u ) ;

58

double [ ] [ ] u=s c i u . g e t R e a l P a r t ( ) ;
System . out . p r i n t l n ( I n t e g r a l a : +u [ 0 ] [ 0 ] ) ;
sci . close ();

18
19
20

}
else {
System . out . p r i n t l n ( Could not s t a r t S c i l a b ) ;
}

21
22
23
24

}
catch ( o r g . s c i l a b . modules . j a v a s c i . J a v a s c i E x c e p t i o n e ) {
System . e r r . p r i n t l n ( An e x c e p t i o n o c c u r e d : + e . g e t L o c a l i z e d M e s s a g e ( ) ) ;
}

25
26
27
28

29
30

CAPITOLUL 2. ACCESAREA IN JAVA A UNOR PRODUSE MATEMATICE

Rezultatele sunt:
Operatia s-a terminat cu succes (true/false) : true
Integrala : 0.27219826128795027

Exemplul 2.3.4 Utilizarea numerelor complexe. Pentru x = 1+2i, y = 1+i se calculeaz


a
produsul x y.
1
2
3
5
6
7
8
9
10
11
12
13
14
15
16
17
18

import o r g . s c i l a b . modules . j a v a s c i . S c i l a b ;
import o r g . s c i l a b . modules . t y p e s . S c i l a b T y p e ;
import o r g . s c i l a b . modules . t y p e s . S c i l a b D o u b l e ;
public c l a s s
TstJavaSci4 {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
try {
S c i l a b s c i=new S c i l a b ( ) ;
i f ( s c i . open ( ) ) {
double [ ] [ ] r e = { { 1 } , { 1 } } ;
double [ ] [ ] im ={{2 ,} ,{ 1}};
S c i l a b D o u b l e s c i z=new S c i l a b D o u b l e ( re , im ) ;
s c i . put ( z , s c i z ) ;
s c i . e x e c ( w=z ( 1 ) z ( 2 ) ) ;
S c i l a b D o u b l e s c i w =( S c i l a b D o u b l e ) s c i . g e t ( w ) ;
double [ ] [ ] w r e=s c i w . g e t R e a l P a r t ( ) ;
double [ ] [ ] w im=s c i w . g e t I m a g i n a r y P a r t ( ) ;
System . out . p r i n t l n ( w r e [ 0 ] [ 0 ] + I +w im [ 0 ] [ 0 ] ) ;
sci . close ();
}
else {
System . out . p r i n t l n ( Could not s t a r t S c i l a b ) ;
}

20
21
22
23
24

}
catch ( o r g . s c i l a b . modules . j a v a s c i . J a v a s c i E x c e p t i o n e ) {
System . e r r . p r i n t l n ( An e x c e p t i o n o c c u r e d : + e . g e t L o c a l i z e d M e s s a g e ( ) ) ;
}

25
26
27
28

29
30

Exemplul 2.3.5 Rezolvarea sistemul algebric de ecuatii

x1 + x 2 + x3 + x4

2x1 x2 + 2x3 x4
x1 + 2x2 x3 + 2x4

2x
x2 + 4x3 + x4

1 +

3x1 + 2x2 2x3 + 2x4


avand solutia x1 = 1, x2 = 1 x4 , x3 = 2.

liniare
=
2
=
1
= 1
=
7
= 5

59

2.3. JAVA CU SCILAB

Sub forma matriceala solutia se scrie



x1
1
x2 1



x3 = 2 +
x4
0

1
c =

0
1


0
1
1

1
+ 2

0
2
1
0
2

0
c .

(2.1)

unde c R.
In Scilab, rezolvarea unui sistem algebric de ecuatii liniare Ax+b = 0, A Mm,n (R), b
n
R , se obtine cu functia [x,k]=linsolve(A,b). x este o solutie particulara a sistemului n timp ce k este o matrice avand drept coloane o baza ortonormata a nucleului
Ker(A) = {x Rn : Ax = 0}. Daca sistemul este incompatibil atunci rezultatele sunt
x = [ ], k = [ ].
1
2
3
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

import o r g . s c i l a b . modules . j a v a s c i . S c i l a b ;
import o r g . s c i l a b . modules . t y p e s . S c i l a b T y p e ;
import o r g . s c i l a b . modules . t y p e s . S c i l a b D o u b l e ;
public c l a s s
TstJavaSci5 {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
try {
S c i l a b s c i=new S c i l a b ( ) ;
i f ( s c i . open ( ) ) {
double [ ] [ ] a = { { 1 , 1 , 1 , 1 } , { 2 , 1 , 2 , 1 } , { 1 , 2 , 1 , 2 } , { 2 , 1 , 4 , 1 } , { 3 , 2 , 2 , 2 } } ;
S c i l a b D o u b l e s c i a=new S c i l a b D o u b l e ( a ) ;
s c i . put ( a , s c i a ) ;
double [ ] [ ] b ={{2} ,{1} ,{ 1} ,{7} ,{ 5}};
S c i l a b D o u b l e s c i b=new S c i l a b D o u b l e ( b ) ;
s c i . put ( b , s c i b ) ;
// b o o l e a n e r r o r=s c i . e x e c ( [ x , k ]= l i n s o l v e (+a+,+b + )) ;
boolean e r r o r=s c i . e x e c ( [ x , k]= l i n s o l v e ( a ,b ) ) ;
System . out . p r i n t l n ( O p e r a t i a sa t e r m i n a t cu s u c c e s ( t r u e / f a l s e ) : +e r r o r ) ;
S c i l a b D o u b l e s c i x =( S c i l a b D o u b l e ) s c i . g e t ( x ) ;
i f ( ! s c i x . isEmpty ( ) ) {
double [ ] [ ] x=s c i x . g e t R e a l P a r t ( ) ;
System . out . p r i n t l n ( x : ) ;
f o r ( i n t i =0; i <x . l e n g t h ; i ++){
f o r ( i n t j =0; j <x [ 0 ] . l e n g t h ; j ++)
System . out . p r i n t ( x [ i ] [ j ]+ ) ;
System . out . p r i n t l n ( ) ;
}
}
S c i l a b D o u b l e s c i k =( S c i l a b D o u b l e ) s c i . g e t ( k ) ;
i f ( ! s c i k . isEmpty ( ) ) {
double [ ] [ ] k=s c i k . g e t R e a l P a r t ( ) ;
System . out . p r i n t l n ( k : ) ;
f o r ( i n t i =0; i <k . l e n g t h ; i ++){
f o r ( i n t j =0; j <k [ 0 ] . l e n g t h ; j ++)
System . out . p r i n t ( k [ i ] [ j ]+ ) ;
System . out . p r i n t l n ( ) ;
}
}
sci . close ();
}
else {
System . out . p r i n t l n ( Could not s t a r t S c i l a b ) ;
}
}
catch ( o r g . s c i l a b . modules . j a v a s c i . J a v a s c i E x c e p t i o n e ) {
System . e r r . p r i n t l n ( An e x c e p t i o n o c c u r e d : + e . g e t L o c a l i z e d M e s s a g e ( ) ) ;
}
}

60

49

CAPITOLUL 2. ACCESAREA IN JAVA A UNOR PRODUSE MATEMATICE

Rezultatele sunt:
Operatia s-a terminat cu succes (true/false) : true
x:
- 1.0000000000000002
0.5000000000000001
2.0000000000000013
0.4999999999999983
k:
8.326672684688674E-17
- 0.7071067811865475
- 3.0531133177191805E-16
0.7071067811865474
1 T
) . Notand cu u si v cele doua solutii particulare
k aproximeaza versorul (0, 12 , 0,
2
puse n evidenta la scrierea solutiei n (2.1) si respectiv cea data de functia linsolve,
u = (1, 1, 2, 0)T , v = (1, 0.5, 2, 0.5)T , vom avea

1
u v = (0, 0.5, 0, 0.5)T = k KerA.
2
Pentru rezolvarea unui sistem algebric de ecuatii liniare de forma Ax = b, extindem
mini-biblioteca mathlib cu o implementare bazata pe functia Scilab linsolve.
Extinderea este ilustrata n schema de mai jos
src
|-->
|
|
|
|
|
|
|
|
|

mathlib
|--> client
|
|
. . .
|
|--> linear
|
|
|--> impl
|
|
|
|
RezolvitorScilab.java // implementeaza interfata
|
|
|
IRezolvitorScilab.java
// interfata
|
|
|
DataIn.java
|
|
|
DataOut.java
|
|
. . .

Codurile claselor adaugate sunt


1. Interfata mathlib.client.linear.IRezolvitorScilab.java
1
2
3
4
5
6
7
8
9
10
11
12

package m a t h l i b . c l i e n t . l i n e a r ;
/
I n t e r f a t a r e z o l v a r i i unui s i s t e m a l g e b r i c de e c u a t i i l i n i a r e
via Scilab .
/
public i n t e r f a c e I R e z o l v i t o r S c i l a b {
/
R e z o l v a r e a unui s i s t e m a l g e b r i c de e c u a t i i l i n i a r e
via Scilab .
/
public DataOut r e z o l v i t o r S c i l a b ( DataIn d i n ) ;
}

2. Clasa mathlib.client.linear.DataIn.java

2.3. JAVA CU SCILAB

1
2
3
4
5
6
7
8
9

package m a t h l i b . c l i e n t . l i n e a r ;
import j a v a . u t i l . V e c t o r ;
import j a v a . i o . B u f f e r e d R e a d e r ;
/
Clasa a c o p e r i t o a r e a d a t e l o r necesare r e z o l v a r i i
unui s i s t e m a l g e b r i c de e c u a t i i l i n i a r e
/
public c l a s s DataIn {
private double [ ] [ ] m a t r i x=n u l l ;
// m a t r i c e a e x t i n s a a s i s t e m u l u i
/
Fixeaza matricea e x t i n s a a s i s t e m u l u i a l g e b r i c .
@param m a t r i x m a t r i c e a e x t i n s a a s i s t e m u l u i .
/
public void s e t M a t r i x ( double [ ] [ ] m a t r i x ) {
t h i s . m a t r i x=m a t r i x ;
}
/
Fixeaza matricea e x t i n s a a s i s t e m u l u i a l g e b r i c .
@param b r f l u x c a r e f u r n i z e a z a m a t r i c e a e x t i n s a a s i s t e m u l u i ;
d a t e l e s u n t t r a n s m i s e pe l i n i i .
/
public void s e t M a t r i x ( B u f f e r e d R e a d e r br ) throws E x c e p t i o n {
Vector<Double> v=new Vector<Double > ( 1 0 ) ;
try {
String line ;
i n t m=0 ,n , mn ;
do{
l i n e=br . r e a d L i n e ( ) ;
i f ( l i n e != n u l l ) {
m++;
S t r i n g [ ] r e s u l t=l i n e . s p l i t ( ) ;
n=r e s u l t . l e n g t h ;
for ( S t r i n g s : r e s u l t )
v . addElement (new Double ( s ) ) ;
}
}
while ( l i n e != n u l l ) ;
i f ( v . s i z e () >0){
mn=v . s i z e ( ) ;
n=mn/m;
m a t r i x=new double [m ] [ n ] ;
f o r ( i n t i =0; i <m; i ++){
f o r ( i n t j =0; j <n ; j ++){
m a t r i x [ i ] [ j ] = ( ( Double ) v . elementAt ( i n+j ) ) . d o u b l e V a l u e ( ) ;
System . out . p r i n t ( m a t r i x [ i ] [ j ]+ ) ;
}
System . out . p r i n t l n ( ) ;
}
}
}
catch ( E x c e p t i o n e ) {
throw new E x c e p t i o n ( e . g e t M e s s a g e ( ) ) ;
}
}
/
Returneaza m a t r i c e a s i s t e m u l u i .
/
public double [ ] [ ] g e t M a t r i x ( ) {
return m a t r i x ;
}

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

Matricea matrix contine ansamblul [A b].

61

62

CAPITOLUL 2. ACCESAREA IN JAVA A UNOR PRODUSE MATEMATICE

Metoda setMatrix(BufferedReader) preia datele dintr-un flux. Elementele matricei


extinse [A b] se transmit n flux, pe linii. Pe o linie separatorul este spatiul. Din
flux se preiau succesiv liniile si se contorizeaza numarul lor. Toate numerele se retin
ntr-o colectie de date de tip java.util.Vector. Impartind numarul elementelor
din colectie la numarul liniilor se gaseste numarul coloanelor. In final, se recompune
matricea cu elementele din colectie.
3. Clasa mathlib.client.linear.DataOut.java
1
2
3
4
5
6
7
8
9
10

package m a t h l i b . c l i e n t . l i n e a r ;
/
Clasa a c o p e r i t o a r e a r e z u l t a t e l o r o b t i n u t e
l a r e z o l v a r e a unui s i s t e m a l g e b r i c de e c u a t i i l i n i a r e
/
public c l a s s DataOut {
private double [ ] x=n u l l ;
// s o l u t i e p a r t i c u l a r a
private double [ ] [ ] k=n u l l ; // b a z a a s p a t i u l u i l i n i a r a l
// s o l u t i i l o r s i s t e m u l u i omogen
private boolean c o m p a t i b i l ;
// n a t u r a s i s t e m u l u i
/
Returneaza o s o l u t i e p a r t i c u l a r a a s i s t e m u l u i .
/
public double [ ] getX ( ) {
return x ;
}
/
Fixeaza o s o l u t i e p a r t i c u l a r a a s i s t e m u l u i .
/
public void setX ( double [ ] x ) {
t h i s . x=x ;
}

12
13
14
15
16
17
18
19
20
21
22
23

/
Returneaza o b a z a n o r m a l i z a t a a s o l u t i i l o r
s i s t e m u l u i omogen .
/
public double [ ] [ ] getK ( ) {
return k ;
}
/
Fixeaza o baza normalizata a s o l u t i i l o r
s i s t e m u l u i omogen .
/
public void setK ( double [ ] [ ] k ) {
t h i s . k=k ;
}

25
26
27
28
29
30
31
32
33
34
35
36
37
38

/
Returneaza n a t u r a s i s t e m u l u i .
/
public boolean i s C o m p a t i b i l ( ) {
return c o m p a t i b i l ;
}
/
Fixeaza natura s i s t e m u l u i .
/
public void s e t C o m p a t i b i l ( boolean c o m p a t i b i l ) {
t h i s . c o m p a t i b i l=c o m p a t i b i l ;
}

40
41
42
43
44
45
46
47
48
49
50
51
52

4. Clasa mathlib.client.linear.impl.RezolvitorScilab.java

2.3. JAVA CU SCILAB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

package m a t h l i b . c l i e n t . l i n e a r . impl ;
import o r g . s c i l a b . modules . j a v a s c i . S c i l a b ;
import o r g . s c i l a b . modules . t y p e s . S c i l a b T y p e ;
import o r g . s c i l a b . modules . t y p e s . S c i l a b D o u b l e ;
import m a t h l i b . c l i e n t . l i n e a r . ;
/
Implementarea r e z o l v a r i i unui s i s t e m a l g e b r i c de e c u a t i i
l i n i a r e prin apelarea f u n c t i e i l i n s o l v e din S c i l a b
/
public c l a s s R e z o l v i t o r S c i l a b implements I R e z o l v i t o r S c i l a b {
/
Metoda de r e z o l v a r e a s i s t e m u l u i a l g e b r i c de e c u a t i i l i n i a r e .
/
public DataOut r e z o l v i t o r S c i l a b ( DataIn d i n ) {
DataOut dout=new DataOut ( ) ;
double [ ] [ ] m a t r i x=d i n . g e t M a t r i x ( ) ;
i n t l=m a t r i x . l e n g t h ;
i n t c=m a t r i x [ 0 ] . l e n g t h ;
double [ ] [ ] a=new double [ l ] [ c 1 ] ;
double [ ] [ ] b=new double [ l ] [ 1 ] ;
f o r ( i n t i =0; i <l ; i ++){
f o r ( i n t j =0; j <c 1; j ++)
a [ i ] [ j ]= m a t r i x [ i ] [ j ] ;
b [ i ] [ 0 ] = matrix [ i ] [ c 1];
}
try {
S c i l a b s c i=new S c i l a b ( ) ;
i f ( s c i . open ( ) ) {
S c i l a b D o u b l e s c i a=new S c i l a b D o u b l e ( a ) ;
s c i . put ( a , s c i a ) ;
S c i l a b D o u b l e s c i b=new S c i l a b D o u b l e ( b ) ;
s c i . put ( b , s c i b ) ;
boolean e r r o r=s c i . e x e c ( [ x , k]= l i n s o l v e ( a ,b ) ) ;
System . out . p r i n t l n ( S u c c e s s f l a g ( t r u e / f a l s e ) : +e r r o r ) ;
S c i l a b D o u b l e s c i x =( S c i l a b D o u b l e ) s c i . g e t ( x ) ;
i f ( ! s c i x . isEmpty ( ) ) {
double [ ] [ ] x=s c i x . g e t R e a l P a r t ( ) ;
double [ ] x1=new double [ x . l e n g t h ] ;
f o r ( i n t i =0; i <x . l e n g t h ; i ++)
x1 [ i ]=x [ i ] [ 0 ] ;
dout . setX ( x1 ) ;
}
S c i l a b D o u b l e s c i k =( S c i l a b D o u b l e ) s c i . g e t ( k ) ;
i f ( ! s c i k . isEmpty ( ) ) {
double [ ] [ ] k=s c i k . g e t R e a l P a r t ( ) ;
dout . setK ( k ) ;
}
i f ( s c i x . g e t R e a l P a r t ( ) . l e n g t h ==0)
dout . s e t C o m p a t i b i l ( f a l s e ) ;
else
dout . s e t C o m p a t i b i l ( true ) ;
sci . close ();
}
else {
System . out . p r i n t l n ( Could not s t a r t S c i l a b ) ;
}
}
catch ( o r g . s c i l a b . modules . j a v a s c i . J a v a s c i E x c e p t i o n e ) {
System . e r r . p r i n t l n ( An e x c e p t i o n o c c u r e d : + e . g e t L o c a l i z e d M e s s a g e ( ) ) ;
}
return dout ;
}
}

63

64

CAPITOLUL 2. ACCESAREA IN JAVA A UNOR PRODUSE MATEMATICE

Capitolul 3
Pachete Java de calcul numeric
In prezent sunt disponibile mai multe pachete de clase Java cu facilitati de calcul
numeric. Dintre cele accesibile gratuit din internet, vom prezenta doar doua produse prin
exemple simple.
Pentru utilizare este nevoie doar de arhiva jar, care se gaseste n catalogul care se
obtine n urma dezarhivarii fisierului descarcat din internet.
De cele mai multe ori, semnificatia parametrilor formali ai metodelor este imediata,
n plus, prezentarea lor se poate citi din descrierea claselor (apidocs).

3.1

apache commons-math

Dezvoltat de fundatia apache, commons-math ofera o colectie bogata de clase pentru


rezolvarea problemelor uzuale de calcul numeric si statistica. Utilizarea claselor se face
potrivit unui sablon unitar, pe care-l vom pune n evidenta prin exemplele ce urmeaza.
commons-math permite lucrul cu fractii ordinare (clasa Fraction), numere complexe
(clasa Complex), matrice reale (clasa RealMatrix).
Dintre facilitatile de calcul numeric amintim:
Rezolvarea unei ecuatii algebrice. Se poate alege dintre metoda bisectiei, metoda
secantei, metoda tangentei (Newton).
Exemplul 3.1.1 Utilizand metoda tangentei (1.1), sa se calculeze solutia negativ
a
x
2
a ecuatiei 2 x = 0.
Functia al carui zero trebuie calculat mpreuna cu structura sa de derivare se fixeaza
ntr-o clasa ce implementeaza interfata UnivariateDifferentiableFunction. 1 .
Pachetul apache commons-math implementeaza metoda derivarii automate. Metoda
nu ncearca sa genereze o aproximatie a derivatei, n schimb utilizeaza o structura
algebrica dublata de o structura de date specifica, denumite structura de derivare
1

Metoda a fost introdus


a de L. B. Rall (1986) iar o prezentare didactica este data de Kalman D., 2002,
Double Recursive Multivariate Automatic Differentiation. Mathematics Magazine, 75, no. 3,187-202.

65

66

CAPITOLUL 3. PACHETE JAVA DE CALCUL NUMERIC

(derivative structure). Calculele se efectueaza utilizand reprezentarea obisnuita a


datelor - n dubla precizie. Astfel va exista o eroare de rotunjire, dar nu va exista o
eroare de metoda.
1
2
3
4
5
6

9
10
11
12
13
14

import o r g . apache . commons . math3 . a n a l y s i s


import o r g . apache . commons . math3 . a n a l y s i s
import o r g . apache . commons . math3 . a n a l y s i s
UnivariateDifferentiableFunction ;
import o r g . apache . commons . math3 . a n a l y s i s
DerivativeStructure ;

. s o l v e r s . NewtonRaphsonSolver ;
. UnivariateFunction ;
. differentiation .
. differentiation .

c l a s s F u n c t i a implements U n i v a r i a t e D i f f e r e n t i a b l e F u n c t i o n {
public D e r i v a t i v e S t r u c t u r e v a l u e ( D e r i v a t i v e S t r u c t u r e x ) {
D e r i v a t i v e S t r u c t u r e t 1=x . m u l t i p l y ( Math . l o g ( 2 ) ) . exp ( ) ;
D e r i v a t i v e S t r u c t u r e t 2=x . pow ( 2 ) ;
return new D e r i v a t i v e S t r u c t u r e ( 1 , t1 , 1 , t 2 ) ;
}
public double v a l u e ( double x ) {
return Math . exp ( xMath . l o g (2)) xx ;
}

16
17
18
19

21

public c l a s s MetodaTangentei {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
U n i v a r i a t e D i f f e r e n t i a b l e F u n c t i o n f u n c t i o n = new F u n c t i a ( ) ;
double a b s o l u t e A c c u r a c y =1.0 e 5;
NewtonRaphsonSolver s o l v e r=
new NewtonRaphsonSolver ( a b s o l u t e A c c u r a c y ) ;
i n t maxEval =1000;
double min = 0.8;
double max= 0.5;
try {
double c = s o l v e r . s o l v e ( maxEval , f u n c t i o n , min , max ) ;
System . out . p r i n t l n ( S o l u t i a : +c ) ;
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( E x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;
}
}
}

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

Rezolvarea unei ecuatii polinomiale utilizand metoda Laguerre. In acest caz se


calculeaza toate radacinile reale si / sau complexe ale unui polinom cu coeficienti
reali sau complecsi.
Exemplul 3.1.2 Sa se calculeze radacinile polinomului
(1+x+x2 )2 (x12i) = x5 +(12i)x4 +(14i)x3 +(16i)x2 +(14i)x12i.
1
2
3
5
6
7
8
9

import o r g . apache . commons . math . a n a l y s i s . s o l v e r s . L a g u e r r e S o l v e r ;


import o r g . apache . commons . math . a n a l y s i s . p o l y n o m i a l s . P o l y n o m i a l F u n c t i o n ;
import o r g . apache . commons . math . complex . Complex ;
public c l a s s MetodaLaguerre {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
double [ ] dummyCoeff = { 1 , 1 } ;
P o l y n o m i a l F u n c t i o n polinom=new P o l y n o m i a l F u n c t i o n ( dummyCoeff ) ;
L a g u e r r e S o l v e r s o l v e r = new L a g u e r r e S o l v e r ( polinom ) ;

3.1. APACHE COMMONS-MATH

Complex i n i t i a l =new Complex ( 1 , 1 ) ;


double [ ] r e a l C o e f f ={ 1 , 1 , 1 ,1 ,1 ,1};
double [ ] i m a g C o e f f ={ 2 , 4 , 6 , 4 , 2 ,0};

10
11
12

i n t grad=r e a l C o e f f . l e n g t h ;
Complex [ ] c o m p l e x C o e f f=new Complex [ grad ] ;
f o r ( i n t i =0; i <grad ; i ++)
c o m p l e x C o e f f [ i ]=new Complex ( r e a l C o e f f [ i ] , i m a g C o e f f [ i ] ) ;
try {
Complex [ ] r o o t s = s o l v e r . s o l v e A l l ( c o m p l e x C o e f f , i n i t i a l ) ;
System . out . p r i n t l n ( R a d a c i n i l e : ) ;
f o r ( i n t i =0; i <grad ; i ++)
System . out . p r i n t l n ( r o o t s [ i ] . g e t R e a l ()+ +I +
roots [ i ] . getImaginary ( ) ) ;
}
catch ( E x c e p t i o n e ) { }

14
15
16
17
18
19
20
21
22
23
24
25

26
27

67

Rezultatele obtinute sunt


Radacinile :
-0.49999991076354433 +I 0.8660254776593728
-0.49999980587362236 +I -0.8660253012543757
1.0000000000000082 +I 2.000000000000006
-0.5000000892365055 +I 0.8660253299095184
-0.5000001941263359 +I -0.8660255063145212

Calculul valorii unei functii de interpolare. Sunt implementate interpolarea cu


functie spline cubica naturala (valoarea derivatei de ordinul doi n punctele de interpolare de abscisa minima si maxima este 0), interpolarea Lagrange (algoritmul
Neville, prin reprezentarea polinomului de interpolare cu diferente divizate).
Exemplul 3.1.3 Sa se calculeze valoarea n 0.5 a functiei spline cubice naturala de
interpolare a functiei f (x) = |x| utilizand nodurile -2,-1,0,1,2.
1
2
3
4
5
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

import
o r g . apache . commons . math . a n a l y s i s . i n t e r p o l a t i o n . S p l i n e I n t e r p o l a t o r ;
import
o r g . apache . commons . math . a n a l y s i s . i n t e r p o l a t i o n . U n i v a r i a t e R e a l I n t e r p o l a t o r ;
import o r g . apache . commons . math . a n a l y s i s . U n i v a r i a t e R e a l F u n c t i o n ;
public c l a s s I n t e r p o l a r e S p l i n e {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
double x [ ] = { 2 , 1 , 0 , 1 , 2 } ;
double y [ ] = { 2 , 1 , 0 , 1 , 2 } ;
try {
U n i v a r i a t e R e a l I n t e r p o l a t o r i n t e r p o l a t o r=new S p l i n e I n t e r p o l a t o r ( ) ;
U n i v a r i a t e R e a l F u n c t i o n f u n c t i o n=i n t e r p o l a t o r . i n t e r p o l a t e ( x , y ) ;
double t = 0 . 5 ;
double z=f u n c t i o n . v a l u e ( t ) ;
System . out . p r i n t l n ( V a l o a r e a i n t e r p o l a t a i n +t+ e s t e +z ) ;
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( E x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;
}
}
}

68

CAPITOLUL 3. PACHETE JAVA DE CALCUL NUMERIC

Integrare numerica. Se poate utiliza metoda trapezelor, metoda Simpson sau metoda
Romberg (extrapolare tip Richardson pornind de la metoda trapezelor).
Exemplul 3.1.4 Sa se calculeze

R
4

ln(1 + tan x)dx =

ln 2 0.2721983.

Utilizand metoda lui Simpson (1.2), codul calculului este


1
2
4
5
6
7
8
10
11
12
13
14
15
16
17
18
19
20
21
22
23

import o r g . apache . commons . math . a n a l y s i s . i n t e g r a t i o n . S i m p s o n I n t e g r a t o r ;


import o r g . apache . commons . math . a n a l y s i s . U n i v a r i a t e R e a l F u n c t i o n ;
c l a s s F u n c t i a implements U n i v a r i a t e R e a l F u n c t i o n {
public double v a l u e ( double x ) {
return Math . l o g (1+Math . tan ( x ) ) ;
}
}
public c l a s s MetodaSimpson {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
U n i v a r i a t e R e a l F u n c t i o n f u n c t i o n = new F u n c t i a ( ) ;
try {
U n i v a r i a t e R e a l I n t e g r a t o r i n t e g r a t o r=
new S i m p s o n I n t e g r a t o r ( f u n c t i o n ) ;
double i n t e g r a l a=i n t e g r a t o r . i n t e g r a t e ( 0 , Math . PI / 4 ) ;
System . out . p r i n t l n ( I n t e g r a l a : +i n t e g r a l a ) ;
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( E x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;
}
}
}

Transformarea Fourier discreta.


Exemplul 3.1.5 Calculul coeficientilor Fourier utilizand transformarea Fourier discreta.
Fie Cn multimea sirurilor de numere complexe, periodice cu perioada n :
Cn = {x = (xk )kZ : xk C, xk = xk+n , k Z}.
Transformarea Fourier discreta este un operator liniar F : Cn Cn definit prin
y = F (x),
yk =

x = (xk )0kn1
n1
X

xj wkj ,

y = (yk )0kn1

0 k n 1,

(3.1)

j=0

unde w = e

i 2
n

. Sirul y se numeste transformata Fourier discreta a sirului x.

Daca f : R R o functie continua si periodica cu perioada 2, atunci are loc


dezvoltarea n serie Fourier

a0 X
f (x) =
+
(ak cos kx + bk sin kx)
2
k=1

(3.2)

69

3.1. APACHE COMMONS-MATH

avand coeficientii
Z
1 2
f (x)dx
a0 =
0

1
ak =

f (x) cos kxdx


0

1
bk =

f (x) sin kxdx


0

pentru k N . Coeficientii Fourier complecsi se definesc prin


Z 2
ak ibk
1
ck =
=
f (x)eikx dx.
2
2 0
Aproximam integrala de mai sus cu formula trapezelor. Daca n N este parametrul
de discretizare atunci se obtine
n1

n1

1 X 2 ik( 2 j)
1 X 2
n
f ( j)e
f ( j)wjk .
ck
=
n j=0
n
n j=0
n

(3.3)

Astfel, sirul c = (ck )0kn1 este aproximat de n1 Fn (y), unde y = (yj )0jn1 , yj =
f ( 2
j).
n
1
2
3
4
6
7
8
9
10
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

import
import
import
import

o r g . apache . commons . math . complex . Complex ;


o r g . apache . commons . math . a n a l y s i s . U n i v a r i a t e R e a l F u n c t i o n ;
o r g . apache . commons . math . t r a n s f o r m . F a s t F o u r i e r T r a n s f o r m e r ;
j a v a . t e x t . DecimalFormat ;

c l a s s F u n c t i a implements U n i v a r i a t e R e a l F u n c t i o n {
public double v a l u e ( double x ) {
return Math . s i n ( x)+Math . c o s ( 3 x ) ;
}
}
public c l a s s C o e f i c i e n t i F o u r i e r {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
i n t n=16;
double e p s=1e 15;
U n i v a r i a t e R e a l F u n c t i o n f u n c t i o n = new F u n c t i a ( ) ;
double [ ] f V a l=new double [ n ] ;
double [ ] a=new double [ n ] ;
double [ ] b=new double [ n ] ;
Complex [ ] f f t =new Complex [ n ] ;
DecimalFormat f=new DecimalFormat ( 0 . 0 0 0 0 E0 ) ;
try {
f o r ( i n t i =0; i <n ; i ++)
f V a l [ i ]= f u n c t i o n . v a l u e ( 2 i Math . PI /n ) ;
F a s t F o u r i e r T r a n s f o r m e r t r a n s f o r m e r=new F a s t F o u r i e r T r a n s f o r m e r ( ) ;
f f t =t r a n s f o r m e r . t r a n s f o r m ( f V a l ) ;
f o r ( i n t i =0; i <n ; i ++){
a [ i ]=2 f f t [ i ] . g e t R e a l ( ) / n ;
i f ( Math . abs ( a [ i ]) < e p s ) a [ i ] = 0 ;
b [ i ]=2 f f t [ i ] . g e t I m a g i n a r y ( ) / n ;
i f ( Math . abs ( b [ i ]) < e p s ) b [ i ] = 0 ;
}
System . out . p r i n t l n ( C o e f i c i e n t i i F o u r i e r : ) ;
f o r ( i n t i =0; i <n / 2 ; i ++)
System . out . p r i n t l n ( a [ +i+ ] = +f . f o r m a t ( a [ i ])+

b [ +i+ ] = +f . f o r m a t ( b [ i ] ) ) ;
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( E x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;
}
}
}

70

CAPITOLUL 3. PACHETE JAVA DE CALCUL NUMERIC

Rezultatele obtinute sunt


Coeficientii Fourier :
a[0] = 0.0000E0
b[0]
a[1] = 0.0000E0
b[1]
a[2] = 0.0000E0
b[2]
a[3] = 1.0000E0
b[3]
a[4] = 0.0000E0
b[4]
a[5] = 0.0000E0
b[5]
a[6] = 0.0000E0
b[6]
a[7] = 0.0000E0
b[7]

=
=
=
=
=
=
=
=

0.0000E0
1.0000E0
0.0000E0
0.0000E0
0.0000E0
0.0000E0
0.0000E0
0.0000E0

Rezolvarea problemelor cu conditii initiale pentru ecuatii si sisteme de ecuatii diferentiale ordinare.
1
2
3
4
5
6
8
9
10
11

import
import
import
import
import
import

o r g . apache . commons . math . ode . F i r s t O r d e r D i f f e r e n t i a l E q u a t i o n s ;


o r g . apache . commons . math . ode . n o n s t i f f . C l a s s i c a l R u n g e K u t t a I n t e g r a t o r ;
o r g . apache . commons . math . ode . F i r s t O r d e r I n t e g r a t o r ;
o r g . apache . commons . math . ode . s a m p l i n g . F i x e d S t e p H a n d l e r ;
o r g . apache . commons . math . ode . s a m p l i n g . S t e p N o r m a l i z e r ;
o r g . apache . commons . math . ode . D e r i v a t i v e E x c e p t i o n ;

c l a s s Problema implements F i r s t O r d e r D i f f e r e n t i a l E q u a t i o n s {
public void c o m p u t e D e r i v a t i v e s ( double t , double [ ] y , double [ ] yDot ) {
yDot [ 0 ] = y [ 0 ] ;
}
public i n t g e t D i m e n s i o n ( ) {
return 1 ;
}

13
14
15
16

18

public c l a s s MetodaRungeKutta {
s t a t i c i n t k=1;
s t a t i c double [ ] [ ] z=new double [ 1 0 1 ] [ 2 ] ;

19
20
22
23
24
25
26
27
28
29
30
31
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

public s t a t i c void main ( S t r i n g [ ] a r g s ) {


Problema ode=new Problema ( ) ;
double pas = 0 . 0 1 ;
i n t n =101;
ClassicalRungeKuttaIntegrator integrator =
new C l a s s i c a l R u n g e K u t t a I n t e g r a t o r ( pas ) ;
double t 0 =0;
double [ ] y0 ={1};
double t=n pas ;
double [ ] y=new double [ y0 . l e n g t h ] ;
F i x e d S t e p H a n d l e r s t e p H a n d l e r 0 = new F i x e d S t e p H a n d l e r ( ) {
public void h a n d l e S t e p ( double t , double [ ] y ,
double [ ] yDot , boolean i s L a s t ) throws D e r i v a t i v e E x c e p t i o n {
k++;
z [ k][0]= t ;
z [ k][1]=y [ 0 ] ;
}
};
S t e p N o r m a l i z e r s t e p H a n d l e r=new S t e p N o r m a l i z e r ( pas , s t e p H a n d l e r 0 ) ;
i n t e g r a t o r . addStepHandler ( s t e p H a n d l e r ) ;
try {
i n t e g r a t o r . i n t e g r a t e ( ode , t0 , y0 , t , y ) ;
f o r ( i n t i =0; i <n ; i ++){
System . out . p r i n t l n ( z [ i ] [ 0 ] + +z [ i ] [ 1 ] ) ;
}
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( E x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;
}

71

3.2. JAMA

52
53

3.2

Jama

Jama - Java matrix contine clase pentru rezolvarea unor probleme de algebra liniara
(matrice; factorizarea LU, QR, Cholesky; valori proprii, descompunerea valorii singulare).
Exemplul 3.2.1 Sa se rezolve sistemul algebric

x1 + 2x2 + 3x3

2x1 + 3x2 + 4x3


3x1 + 4x2 + x3

4x1 + x2 + 2x3

de ecuatii liniare
+ 4x4
+ x4
+ 2x4
+ 3x4

=
=
=
=

11
12
13
14

Pentru rezolvarea unui sistem Ax = b, metoda solve a clasei Matrix se poate folosi doar
n cazul matricei A nesingulare. Codul rezolvarii este extrem de simplu:
1
2
3
5
6
7
8
9

import Jama . ;
import j a v a . i o . ;
import j a v a . t e x t . ;
public c l a s s S i s t e m L i n i a r {
public s t a t i c void main ( S t r i n g a r g s [ ] ) {
double [ ] [ ] a = { { 1 , 2 , 3 , 4 } , { 2 , 3 , 4 , 1 } , { 3 , 4 , 1 , 2 } , { 4 , 1 , 2 , 3 } } ;
double [ ] b = { 1 1 , 1 2 , 1 3 , 1 4 } ;
i n t n=a . l e n g t h ;
Matrix A=new Matrix ( a ) ;
Matrix B=new Matrix ( b , n ) ;
Matrix X=A. s o l v e (B ) ;
System . out . p r i n t l n ( S o l u t i a ) ;
X. p r i n t ( NumberFormat . g e t N u m b e r I n s t a n c e ( ) , 1 0 ) ;

11
12
13
14
15

16
17

Exemplul 3.2.2 Sa se determine factorizarea LU a matricei

1
2 1 3
2
2
4 2 5
1

A = 1 2 1 3 4
.
3
6
2 10 7
1
2
4
0
4
Din nou codul este explicit:
1
2
3
5
6
7
8

import Jama . ;
import j a v a . i o . ;
import j a v a . t e x t . ;
public c l a s s LUfact {
public s t a t i c void main ( S t r i n g a r g s [ ] ) {
double [ ] [ ] a ={{1 ,2 , 1 ,3 ,2} ,{2 ,4 , 2 ,5 ,1} ,{ 1 , 2 ,1 , 3 , 4} ,
{3 ,6 ,2 ,10 ,7} ,{1 ,2 ,4 ,0 ,4}};

72

i n t n=a . l e n g t h ;

Matrix l , u , p , v ;
int [ ] piv ;
Matrix m=new Matrix ( a ) ;
LUDecomposition l u=m. l u ( ) ;
l=l u . getL ( ) ;
u=l u . getU ( ) ;
p i v=l u . g e t P i v o t ( ) ;
System . out . p r i n t l n ( M a t r i c e a L ) ;
l . p r i n t ( NumberFormat . g e t N u m b e r I n s t a n c e ( ) , 1 0 ) ;
System . out . p r i n t l n ( M a t r i c e a U ) ;
u . p r i n t ( NumberFormat . g e t N u m b e r I n s t a n c e ( ) , 1 0 ) ;
System . out . p r i n t l n ( M a t r i c e a P ) ;
p=new Matrix ( n , n ) ;
f o r ( i n t i =0; i <n ; i ++)
p . s e t ( i , piv [ i ] , 1 ) ;
p . p r i n t ( NumberFormat . g e t N u m b e r I n s t a n c e ( ) , 1 0 ) ;

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

System . out . p r i n t l n ( V e r i f i c a r e : P A L U = 0 ( ? ) ) ;
v=new Matrix ( n , n ) ;
v=p . t i m e s (m) . minus ( l . t i m e s ( u ) ) ;
v . p r i n t ( NumberFormat . g e t N u m b e r I n s t a n c e ( ) , 1 0 ) ;

28
29
30
31

32
33

CAPITOLUL 3. PACHETE JAVA DE CALCUL NUMERIC

cu rezultatele
Matricea L
1
0.667
0.333
0.333
-0.333

0
1
0
0
0

0
0
1
-0.5
0.5

0
0
0
1
-1

0
0
0
0
1

6
0
0
0
0

2
-3.333
3.333
0
0

10
-1.667
-3.333
-2
0

7
-3.667
1.667
0.5
-2

0
1
0
0
0

0
0
0
0
1

1
0
0
0
0

0
0
1
0
0

0
0
0
0
0

0
0
0
0
0

Matricea U
3
0
0
0
0
Matricea P
0
0
0
1
0

Verificare : P A - L U = 0 (?)
0
0
0
0
0

0
0
0
0
0

0
-0
0
-0
0

Capitolul 4
Calcul simbolic n Java
Cel mai simplu mod de efectuare a unor calcule simbolice ntr-un program Java este
prin intermediul produselor Mathematica, Maple.
Symja - Java Computer Algebra Library este o biblioteca de pachete Java pentru calcul
simbolic (https://bitbucket.org/axelclk/symja_android_library/wiki/Home) dar
si numeric.

4.1

Calcul simbolic prin Mathematica

Structura unui program Java care apeleaza o functie Mathematica de calcul simbolic
este cea prezentata n 2.1.
Apelarea si generarea rezultatului sub forma uzuala din consola Mathematica se obtine
cu functia clasei com.wolfram.jlink.KernelLink
evaluateToOutputForm(String apelMathematica, 0)
Pentru descompunerea n factori a expresiei algebrice (x+y)7 x7 y 7 codul de apelare
a functiei Factor este
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

import com . wolfram . j l i n k . ;


public c l a s s F a c t o r {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
K e r n e l L i n k ml=n u l l ;
try {
S t r i n g [ ] mlArgs = { linkmode , l a u n c h , linkname , a r g s [ 0 ] } ;
ml = MathLinkFactory . c r e a t e K e r n e l L i n k ( mlArgs ) ;
}
catch ( MathLinkException e ) {
System . out . p r i n t l n ( F a t a l o p e n i n g l i n k e r r o r : +e . g e t M e s s a g e ( ) ) ;
System . e x i t ( 1 ) ;
}
try {
ml . d i s c a r d A n s w e r ( ) ;
S t r i n g r e s u l t=ml . evaluateToOutputForm ( F a c t o r [ ( x+y)7x7y 7 ] , 0 ) ;
System . out . p r i n t l n ( F a c t o r [ ( x+y)7x7y 7 ] ) ;
System . out . p r i n t l n ( r e s u l t ) ;
}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( MathLinkException : +e . g e t M e s s a g e ( ) ) ;
}

73

74
finally {
ml . c l o s e ( ) ;
}

22
23
24

25
26

CAPITOLUL 4. CALCUL SIMBOLIC IN JAVA

Rezultatul va fi
Factor[(x + y)7 x7 y7 ]
7xy(x + y)(x2 + xy + y 2 )2

Analog
R
integrala 04 ln (1 + tan x)dx se calculeaza cu functia Integrate[Log[1+Tan[x]],x,
.
0,Pi/4] din Mathematica. Se obtine: Pi Log[2]
8
problema cu valoare initiala y+y

tan x = cos1 x , y(0) = 1 se calculeaza cu DSolve[y[x]


+y[x] Tan[x]==1/Cos[x],y[0]==1,y[x],x]. Rezultatul este {{y[x] Cos[x]+Sin[x]}}.

4.2

Calcul simbolic prin Maple

Sablonul de programare coincide cu cel prezentat n sectiunea 2.2. Pentru descompunerea n factori a expresiei algebrice (x + y)7 x7 y 7 codul este
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

import com . m a p l e s o f t . openmaple . ;


import com . m a p l e s o f t . e x t e r n a l c a l l . MapleException ;
class Factor {
public s t a t i c void main ( S t r i n g a r g s [ ] ) {
try {
S t r i n g [ ] argsMaple={ j a v a } ;
Engine e n g i n e=new Engine ( argsMaple , new E n g i n e C a l l B a c k s D e f a u l t ( ) , null , n u l l ) ;
A l g e b r a i c s o l=e n g i n e . e v a l u a t e ( f a c t o r ( ( x+y)7x7y 7 ) ; ) ;
}
catch ( MapleException e ) {
System . out . p r i n t l n ( MapleException : +e . g e t M e s s a g e ( ) ) ;
return ;
}
}
}

Rezultatul este

7*x*y*(x+y)*(x^2+x*y+y^2)^2

Daca expresia de evaluat este problema cu valore initiala


dsolve(diff(y(x),x)+y(x)*tan(x)-1/cos(x)=0,y(0)=1,y(x));
atunci se obtine

y(x)=cos(x)*tan(x)+cos(x)

. Pentru expresia

simplify(dsolve(diff(y(x),x)+y(x)*tan(x)-1/cos(x)=0,y(0)=1,y(x)));
se va obtine

y(x)=sin(x)+cos(x)

4.3. SYMJA - JAVA COMPUTER ALGEBRA LIBRARY

4.3

75

Symja - Java Computer Algebra Library

Resursele necesare variantei curente sunt:


COMMONS MATH4 SYMJA.jar
symja-*.jar
log4j-1.2.17.jar
Sintaxa utilizata este cea din Mathematica, dar n editarea expresiilor de calcul nu se
face distinctie ntre literele mari si mici iar parantezele patrate pot fi nlocuite cu paranteze
rotunde. Astfel expresiile
Factor[(x+y)^7-x^7-y^7]
factor[(x+y)^7-x^7-y^7]
factor((x+y)^7-x^7-y^7)

sunt echivalente.
Trebuie subliniat ca posibilitatile de calcul simbolic nu coincid cu cele din Mathematica.
Sablonul de programare este
ExprEvaluator util = new ExprEvaluator();
IExpr result=util.evaluate("Expresia de calcul");
System.out.println(result.toString());

In exemplul urmator se calculeaza:


1. descompunerea n factori a expresiei (x + y)7 x7 y 7 ;
2.

d sin 2x cos x
;
dx

3.

d2 arctan x
;
dx2

4.

5.

1
dx;
1+x4
0

1
dx;
1+x2

cu codul Java
1
2
4
5
6
7
8
9
11
12
14
15
17
18
20
21

import o r g . m a t h e c l i p s e . c o r e . e v a l . E x p r E v a l u a t o r ;
import o r g . m a t h e c l i p s e . c o r e . i n t e r f a c e s . IExpr ;
public c l a s s ESymja{
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
try {
E x p r E v a l u a t o r u t i l = new E x p r E v a l u a t o r ( ) ;
IExpr r e s u l t=u t i l . e v a l u a t e ( F a c t o r [ ( x+y)7x7y 7 ] ) ;
System . out . p r i n t l n ( r e s u l t . t o S t r i n g ( ) ) ;
r e s u l t = u t i l . e v a l u a t e ( D[ S i n [ 2 x ] Cos [ x ] , x ] ) ;
System . out . p r i n t l n ( r e s u l t . t o S t r i n g ( ) ) ;
r e s u l t = u t i l . e v a l u a t e ( D[ ArcTan [ x ] , { x , 2 } ] ) ;
System . out . p r i n t l n ( r e s u l t . t o S t r i n g ( ) ) ;
r e s u l t = u t i l . e v a l u a t e ( I n t e g r a t e [1 /( 1+ x 4 ) , x ] ) ;
System . out . p r i n t l n ( r e s u l t . t o S t r i n g ( ) ) ;
r e s u l t = u t i l . e v a l u a t e ( I n t e g r a t e [1 /( 1+ x 2 ) , { x , 0 , I n f i n i t y } ] ) ;
System . out . p r i n t l n ( r e s u l t . t o S t r i n g ( ) ) ;

76
}
catch ( E x c e p t i o n e ) {
e . printStackTrace ( ) ;
}

22
23
24
25

26
27

CAPITOLUL 4. CALCUL SIMBOLIC IN JAVA

Rezultatele sunt, respectiv


1.
7*(x+y)*x*y*(x^2+x*y+y^2)^2
2.
2*Cos(x)*Cos(2*x)-Sin(x)*Sin(2*x)
3.
(-2*x)/(1+x^2)^2
1/2*(-ArcTan(1+(-2*x)/Sqrt(2))/Sqrt(2)+ArcTan(1+(2*x)/Sqrt(2))/Sqrt(2))+
1/2*(Log(1+x*Sqrt(2)+x^2)/(2*Sqrt(2))-Log(1-x*Sqrt(2)+x^2)/(2*Sqrt(2)))
4.
Pi/2

Capitolul 5
Expresie de calcul dat
a ca String
Executia unui program de calcul stiintific poate solicita furnizarea de catre client a
unor expresii de calcul. Acestea pot reprezenta membrul stang al unei ecuatii algebrice
f (x) = 0 sau membrul drept al unei ecuatii diferentiele ordinare x = f (x), etc. Expresia
de calcul, notata prin f (x), poate contine simboluri matematice uzuale, chiar nume de
functii.
String-ul introdus de client trebuie interpretat de programul de calcul ca o expresie de
evaluat, chiar permitand evaluarea ei pentru tot felul de valori date parametrilor.
Scopul acestui capitol este prezentarea de solutii pentru aceste probleme.
Vom utiliza produsele informatice:
Java Expression Parser - JEP;
MathEclipse Parser.
In afara acestora semnalam existenta urmatoarelor softuri exp4j, javaluator cat si posibilitatea utilizarii motorului Javascript din Java.

5.1

Java Expression Parser - JEP

JEP este probabil produsul cel mai reprezentativ pentru problema enuntata. Pana la
versiunea 2.4.1, JEP a fost un produs gratuit, versiunile urmatoare fiind produse comerciale. Astfel, ne vom limita doar la versiunea gratuita 2.4.1.
Variabila de sistem classpath trebuie sa contina referinta catre jep-2.4.1.jar.
Utilizarea produsului. Evaluarea unei expresii n care intervin variabile se obtine
prin
1. Generarea unui convertor JEP
JEP parser=new JEP();
2. Definirea variabilelor. Daca variabila var are valoarea val definirea ei se face prin
parser.addVariable(var,val);
77

78

CA STRING
CAPITOLUL 5. EXPRESIE DE CALCUL DATA

3. Definirea expresiei / formulei de evaluat. Expresia de calcul data de stringul s exp


se introduce prin
parser.parseExpression(s exp);
4. Rezultatul evaluarii se obtine prin
parser.getValue();
Operatiile aritmetice se indica n mod obisnuit prin
adunare
nmultire
ridicare la putere

+ scadere
* mpartire

Daca am dori sa calculam expresia x2 + y 2 pentru x = 3 si y = 4, atunci codul este


1

import o r g . nfunk . j e p . ;

c l a s s TestJep1 {
public s t a t i c void main ( S t r i n g a r g s [ ] ) {
double x=3 ,y =4;
S t r i n g s e x p=x2+y 2 ;
JEP p a r s e r=new JEP ( ) ;
p a r s e r . a d d V a r i a b l e ( x , x ) ;
p a r s e r . a d d V a r i a b l e ( y , y ) ;
parser . parseExpression ( s exp ) ;
double r e z u l t a t=p a r s e r . g e t V a l u e ( ) ;
System . out . p r i n t l n ( R e z u l t a t : +r e z u l t a t ) ;
}
}

4
5
6
7
8
9
10
11
12
13
14

Functiile uzuale recunoscute de JEP sunt:


sin(x)
cos(x)
tg(x)
sh(x)
ch(x)
th(x)
ex
lg(x)

sin(x) arcsin(x) asin(x)


cos(x) arccos(x) acos(x)
tan(x) arctg(x) atan(x)
sinh(x) arcsh(x) asinh(x)
cosh(x) arcch(x) acosh(x)
tanh(x) arcth(x) atanh(x)
exp(x)
ln(x)
ln(x)
log(x)
|x|
abs(x)
sqrt(x)

Constantele recunoscute de JEP sunt:

e e pi i = 1 i
Recunoasterea acestor functii si constante presupune declararea lor:
parser.addStandardFunctions();
parser.addStandardConstants();

5.1. JAVA EXPRESSION PARSER - JEP

79

Calculul expresiei sin 4 + sin 3 este


double x=Math.PI/3;
double y=Math.PI/4;
String s_exp="sin(x)+sin(y)";
JEP parser=new JEP();
parser.addStandardFunctions();
parser.addStandardConstants();
parser.addVariable("x",x);
parser.addVariable("y",y);
parser.parseExpression(s_exp);
double rezultat=parser.getValue();

Colectia de functiiRrecunoscute de JEP se poate extinde. Exemplificam cu includerea


2
x
functiei erf(x) = 2 0 et dt, pe care o preluam din pachetul
org.apache.commons.math.
In acest sens, sablonul de programare solicita definirea unei clase de forma
1
2
3
4
6
7
8
9

import
import
import
import

c l a s s J e p E r f extends PostfixMathCommand {
public J e p E r f ( ) {
numberOfParameters = 1 ;
}
public void run ( S t a c k i n S t a c k ) throws P a r s e E x c e p t i o n {
checkStack ( inStack ) ;
O b j e c t param = i n S t a c k . pop ( ) ;
i f ( param instanceof Double ) {
try {
double r =0 ,x =(( Double ) param ) . d o u b l e V a l u e ( ) ;
i f ( Math . abs ( x ) <26)
r = Erf . e r f ( x ) ;
else {
i f ( x>0)
r =1;
else
r =1;
}
i n S t a c k . push (new Double ( r ) ) ;
}
catch ( E x c e p t i o n e ) {
throw new P a r s e E x c e p t i o n ( e . g e t M e s s a g e ( ) ) ;
}
}
else {
throw new P a r s e E x c e p t i o n ( I n v a l i d p a r a m e t e r t y p e ) ;
}
}

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

java . u t i l . ;
o r g . nfunk . j e p . ;
o r g . nfunk . j e p . f u n c t i o n . ;
o r g . apache . commons . math3 . s p e c i a l . ;

In vederea utilizarii, noua functie se declara prin


parser.addFunction("erf", new JepErf());
erf reprezinta numele sub care se recunoaste functia ntr-un string, iar JepErf este numele
clasei ce evalueaza functia. In urma acestei operatii, funtia erf va putea fi evaluata, la fel
ca oricare alta functie.
Calculul valorii erf(10) 1 consta din

80

CA STRING
CAPITOLUL 5. EXPRESIE DE CALCUL DATA

double x=10;
String s_exp="erf(x)";
JEP parser=new JEP();
parser.addStandardFunctions();
parser.addStandardConstants();
parser.addFunction("erf", new JepErf());
parser.addVariable("x",x);
parser.parseExpression(s_exp);
double rezultat=parser.getValue();

5.2

MathEclipse-Parser

MathEclipse-Parser este un produs gratuit care evalueaza numeric expresiile de calcul


date ca string si n plus poate fi ncorporat ca modul n Google Web Toolkit (GWT).
A doua modalitate de folosire este motivul pentru care ne-am oprit asupra acestui
produs informatic.
In cele ce urmeaza, vom ilustra cateva facilitati ale lui MathEclipse-Parser. Se utilizeaza fisierul descarcat matheclipse-parser-*.jar, iar pentru includerea n GWT
acesta trebuie dezarhivat.
MathEclipse-Parser ofera posibilitatea de lucru cu variabile reale - de tip predefinit
double dar si cu variabile complexe.

Prelucrarea expresiilor reale


Maniera de lucru este asemanatoare cu cea din JEP:
1. Generarea unui motor de evaluare (parser ).
DoubleEvaluator engine = new DoubleEvaluator();
2. Definirea variabilelor.
IDoubleValue vx = new DoubleVariable(val);
engine.defineVariable("x",vx);
3. Definirea expresiei / formulei de evaluat. Expresia de calcul data de stringul s exp
contine simbolul x.
Binenteles, se pot defini atatea variabile de cate este nevoie.
Numele functiilor coincid cu cele din Mathematica, iar argumentele se scriu ntre
paranteze drepte.
4. Rezultatul evaluarii expresiei s exp se obtine prin
double rezultat = engine.evaluate(s expr);

5.2. MATHECLIPSE-PARSER

81

Constantele recunoscute de MathEclipse-Parser sunt:


e E

Pi

Astfel evaluarea expresiei x2 + y 2 pentru x = 3 si y = 4, are codul


double x=3,y=4;
String s_expr="x^2+y^2";
IDoubleValue vx = new DoubleVariable(x);
IDoubleValue vy = new DoubleVariable(y);
DoubleEvaluator engine = new DoubleEvaluator();
engine.defineVariable("x",vx);
engine.defineVariable("y",vy);
double rezultat = engine.evaluate(s_expr);

iar calculul expresiei sin 4 + sin 3 este


String s_expr="Sin[Pi/3]+Sin[Pi/4]";
DoubleEvaluator engine = new DoubleEvaluator();
double rezultat = engine.evaluate(s_expr);

Prelucrarea expresiilor complexe


Analiza urmatorului program, scoate n evidenta posibilitatile oferite, cat si maniera
de programare
1
2
3
5
6
7
8
9
11
12
13
15
16
18
19
21
22
24
25
27
28
29
31
32

import o r g . m a t h e c l i p s e . p a r s e r . c l i e n t . e v a l . ;
import o r g . m a t h e c l i p s e . p a r s e r . c l i e n t . math . ;
public c l a s s E x p r e s i i C o m p l e x e {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
try {
Complex z=new Complex ( 1 , 3 ) ;
System . out . p r i n t ( z= ) ;
System . out . p r i n t l n ( ComplexEvaluator . t o S t r i n g ( z ) ) ;
System . out . p r i n t l n ( C o n j u g a t u l ) ;
Complex w=z . c o n j u g a t e ( ) ;
System . out . p r i n t l n ( ComplexEvaluator . t o S t r i n g (w ) ) ;
System . out . p r i n t l n ( Suma ) ;
System . out . p r i n t l n ( ComplexEvaluator . t o S t r i n g ( z . add (w ) ) ) ;
System . out . p r i n t l n ( P r o d u s u l ) ;
System . out . p r i n t l n ( ComplexEvaluator . t o S t r i n g ( z . m u l t i p l y (w ) ) ) ;
System . out . p r i n t l n ( Catul ) ;
System . out . p r i n t l n ( ComplexEvaluator . t o S t r i n g ( z . d i v i d e (w ) ) ) ;
System . out . p r i n t l n ( Modulul ) ;
System . out . p r i n t l n ( z . abs ( ) ) ;
System . out . p r i n t l n ( \ n F u n c t i i complexe ) ;
System . out . p r i n t l n ( s i n ( z ) ) ;
System . out . p r i n t l n ( ComplexEvaluator . t o S t r i n g ( z . s i n ( ) ) ) ;
System . out . p r i n t l n ( c o s ( z ) ) ;
System . out . p r i n t l n ( ComplexEvaluator . t o S t r i n g ( z . c o s ( ) ) ) ;

35

System . out . p r i n t l n ( tan ( z ) ) ;


System . out . p r i n t l n ( ComplexEvaluator . t o S t r i n g ( z . tan ( ) ) ) ;

37

System . out . p r i n t l n ( s i n h ( z ) ) ;

34

82

Complex u=z . s i n h ( ) ;
System . out . p r i n t l n ( ComplexEvaluator . t o S t r i n g ( u ) ) ;

38
39

System . out . p r i n t l n ( c o s h ( z ) ) ;
Complex v=z . c o s h ( ) ;
System . out . p r i n t l n ( ComplexEvaluator . t o S t r i n g ( v ) ) ;

41
42
43

System . out . p r i n t l n ( tanh ( z ) ) ;


System . out . p r i n t l n ( ComplexEvaluator . t o S t r i n g ( z . tanh ( ) ) ) ;

45
46

System . out . p r i n t l n ( \ n E v a l u a r e a e x p r e s i i l o r complexe ) ;


System . out . p r i n t l n ( c o s h 2 ( z) s i n h 2 ( z ) ) ;
ComplexVariable cu = new ComplexVariable ( u ) ;
ComplexVariable cv = new ComplexVariable ( v ) ;
ComplexEvaluator e n g i n e = new ComplexEvaluator ( ) ;
S t r i n g e x p r=v2u2 ;
e n g i n e . d e f i n e V a r i a b l e ( u , cu ) ;
e n g i n e . d e f i n e V a r i a b l e ( v , cv ) ;
Complex r=e n g i n e . e v a l u a t e ( e x p r ) ;
System . out . p r i n t l n ( ComplexEvaluator . t o S t r i n g ( r ) ) ;

48
49
50
51
52
53
54
55
56
57

}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( e . g e t M e s s a g e ( ) ) ;
}

58
59
60
61

62
63

CA STRING
CAPITOLUL 5. EXPRESIE DE CALCUL DATA

Capitolul 6
Aplicatii cu interfat
a grafic
a
Atasam o interfata grafica unor aplicatii dezvoltate n capitolele anterioare. Prin intermediul interfetei grafice, un client (utilizator) introduce datele si primeste afisat rezultatul
problemei.
Programarea interfetei grafice se poate baza pe resursele oferite de pachetele javax.swing
si javafx din distributia Java.
Utilizarea mediului integrat de programare (Integrated Development Environment IDE) Netbeans, www.netbeans.org, usureaza mult munca de programare.

6.1

Rezolvarea unei ecuatii algebrice

Expresia functiei este introdusa de client sub forma unui string. Aplicand rezultatele
anterioare, extindem mini-biblioteca prezentata n primul capitol cu clase de tip DataIn
care implementeaza corespunzator metoda public double fct(double x).
Componenta Java care retine datele problemei, bazat pe JEP (clasa mathlib.client.
ecalg.JepDataIn), are codul
1
2
3
4
5
6
7
8
9
10
12
13
14
15
16
17
18
19
20
21
22
23
24

package m a t h l i b . c l i e n t . e c a l g ;
import o r g . nfunk . j e p . ;
/
E x t i n d e r e a c l a s e i DataIn cu p r e l u a r e a unor d a t e
ca S t r i n g u r i c a r e s u n t c o n v e r t i t e i n v a l o r i numerice
p r i n p a c h e t u l JEP ( Java E x p r e s s i o n P a r s e r )
/
public c l a s s JepDataIn extends DataIn {
private JEP p a r s e r=n u l l ;
private S t r i n g v a r ;
/
Constructorul c l a s e i care i n s t a n t i a z a s i c a l i b r e a z a
o b i e c t u l JEP u t i l i z a t l a p e n t r u e v a l u a r e a f u n c t i e i .
@param v a r S i m b o l u l v a r i a b i l e i .
@param e x p r E x t r e s i a f u n c t i e i .
/
public JepDataIn ( S t r i n g var , S t r i n g e x p r ) {
t h i s . v a r=v a r ;
p a r s e r=new JEP ( ) ;
p a r s e r . addStandardFunctions ( ) ;
p a r s e r . addStandardConstants ( ) ;
p a r s e r . a d d V a r i a b l e ( var , 0 ) ;
p a r s e r . p ar s eE xp re ss i on ( expr ) ;

83

84

GRAFICA

CAPITOLUL 6. APLICAT
II CU INTERFAT
A

25

27

/
F u n c t i a c o r e s p u n z a t o a r e membrului s t a n g a l e c u a t i e i f c t ( x )=0.
/
public double f c t ( double x ) {
p a r s e r . a d d V a r i a b l e ( var , x ) ;
return p a r s e r . g e t V a l u e ( ) ;
}

28
29
30
31
32
33
34

Reluam problema rezolvarii ecuatiei algebrice f (x) = 0 din 1.2.

6.1.1

Interfata grafic
a bazat
a pe JavaFX

Codul clasei cu interfata grafica bazata pe pachetele javafx este


1

package e c u a t i e f x ;

import
import
import
import

javafx
javafx
javafx
javafx

18

import
import
import
import
import
import
import
import
import
import
import

j a v a f x . scene . paint . Color ;


j a v a f x . stage . Stage ;
j a v a f x . scene . c o n t r o l . Label ;
javafx . scene . control . TextField ;
j a v a f x . s c e n e . l a y o u t . GridPane ;
j a v a f x . s c e n e . c o n t r o l . Button ;
j a v a f x . e v e n t . EventHandler ;
j a v a f x . s c e n e . i n p u t . MouseEvent ;
j a v a . t e x t . DecimalFormat ;
mathlib . c l i e n t . e c a l g . ;
m a t h l i b . c l i e n t . e c a l g . impl . MetodaTangenteiWeb ;

20

public c l a s s E c u a t i e f x extends A p p l i c a t i o n {

4
5
6
8
9
10
11
12
13
14
15
16
17

22
23
24
26
27
28
29
30

. application . Application ;
. e v e n t . ActionEvent ;
. s c e n e . Group ;
. s c e n e . Scene ;

public s t a t i c void main ( S t r i n g [ ] a r g s ) {


Application . launch ( Ecuatiefx . class , args ) ;
}
@Override
public void s t a r t ( S t a g e p r i m a r y S t a g e ) {
p r i m a r y S t a g e . s e t T i t l e ( Metoda t a n g e n t e i ) ;
Group r o o t = new Group ( ) ;
Scene s c e n e = new Scene ( r o o t , 6 0 0 , 2 5 0 , C o l o r .LIGHTGREEN ) ;

32

GridPane g r i d p a n e=new GridPane ( ) ;

34

L a b e l l a b e l V a r=new L a b e l ( V a r i a b i l a ) ;
GridPane . s e t C o n s t r a i n t s ( l a b e l V a r , 1 , 1 ) ;
L a b e l l a b e l A p r o x=new L a b e l ( Aproximatia i n i t i a l a ) ;
GridPane . s e t C o n s t r a i n t s ( l a b e l A p r o x , 1 , 2 ) ;
L a b e l l a b e l E x p r=new L a b e l ( E x p r e s i a membrului s t a n g ) ;
GridPane . s e t C o n s t r a i n t s ( l a b e l E x p r , 1 , 3 ) ;
L a b e l l a b e l T o l=new L a b e l ( T o l e r a n t a ) ;
GridPane . s e t C o n s t r a i n t s ( l a b e l T o l , 1 , 4 ) ;
L a b e l l a b e l N m i=new L a b e l ( Numar maxim de i t e r a t i i ) ;
GridPane . s e t C o n s t r a i n t s ( labelNmi , 1 , 5 ) ;

35
36
37
38
39
40
41
42
43
45
46
47
48

f i n a l T e x t F i e l d T e x t F i e l d V a r=new T e x t F i e l d ( ) ;
GridPane . s e t C o n s t r a i n t s ( TextFieldVar , 2 , 1 ) ;
f i n a l T e x t F i e l d TextFieldAprox=new T e x t F i e l d ( ) ;
GridPane . s e t C o n s t r a i n t s ( TextFieldAprox , 2 , 2 ) ;

6.1. REZOLVAREA UNEI ECUAT


II ALGEBRICE

49
50
51
52
53
54
56
57
58
59
60
61
62
63
65
66
67
68
69
70
71
72
73
74
75
76
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
104
105
106
107
108
109
110
111
112
113
114
115

f i n a l T e x t F i e l d T e x t F i e l d E x p r=new T e x t F i e l d ( ) ;
GridPane . s e t C o n s t r a i n t s ( TextFieldExpr , 2 , 3 ) ;
f i n a l T e x t F i e l d T e x t F i e l d T o l=new T e x t F i e l d ( 1 . 0 e8 ) ;
GridPane . s e t C o n s t r a i n t s ( T e x t F i e l d T o l , 2 , 4 ) ;
f i n a l T e x t F i e l d TextFieldNmi=new T e x t F i e l d ( 50 ) ;
GridPane . s e t C o n s t r a i n t s ( TextFieldNmi , 2 , 5 ) ;
L a b e l l a b e l I n d=new L a b e l ( I n d i c a t o r u l de r a s p u n s ) ;
GridPane . s e t C o n s t r a i n t s ( l a b e l I n d , 3 , 1 ) ;
L a b e l l a b e l S o l=new L a b e l ( S o l u t i a ) ;
GridPane . s e t C o n s t r a i n t s ( l a b e l S o l , 3 , 2 ) ;
L a b e l l a b e l V a l=new L a b e l ( V a l o a r e a i n s o l u t i e ) ;
GridPane . s e t C o n s t r a i n t s ( l a b e l V a l , 3 , 3 ) ;
L a b e l l a b e l I t e r=new L a b e l ( Numar de i t e r a t i i ) ;
GridPane . s e t C o n s t r a i n t s ( l a b e l I t e r , 3 , 4 ) ;
f i n a l T e x t F i e l d T e x t F i e l d I n d=new T e x t F i e l d ( ) ;
TextFieldInd . s e t V i s i b l e ( false ) ;
GridPane . s e t C o n s t r a i n t s ( T e x t F i e l d I n d , 4 , 1 ) ;
f i n a l T e x t F i e l d T e x t F i e l d S o l=new T e x t F i e l d ( ) ;
TextFieldSol . s e t V i s i b l e ( false ) ;
GridPane . s e t C o n s t r a i n t s ( T e x t F i e l d S o l , 4 , 2 ) ;
f i n a l T e x t F i e l d T e x t F i e l d V a l=new T e x t F i e l d ( ) ;
TextFieldVal . s e t V i s i b l e ( false ) ;
GridPane . s e t C o n s t r a i n t s ( T e x t F i e l d V a l , 4 , 3 ) ;
f i n a l T e x t F i e l d T e x t F i e l d I t e r=new T e x t F i e l d ( ) ;
TextFieldIter . setVisible ( false ) ;
GridPane . s e t C o n s t r a i n t s ( T e x t F i e l d I t e r , 4 , 4 ) ;
Button btn=new Button ( C a l c u l e a z a ) ;
GridPane . s e t C o n s t r a i n t s ( btn , 2 , 6 ) ;
btn . se tO nA ct io n ( (new EventHandler<ActionEvent >() {
public void h a n d l e ( ActionEvent me) {
S t r i n g v a r=T e x t F i e l d V a r . g e t T e x t ( ) ;
S t r i n g e x p r=T e x t F i e l d E x p r . g e t T e x t ( ) ;
DataIn d i n=new JepDataIn ( var , e x p r ) ;
d i n . setX ( (new Double ( TextFieldAprox . g e t T e x t ( ) ) ) . d o u b l e V a l u e ( ) ) ;
d i n . s e t E p s ( (new Double ( T e x t F i e l d T o l . g e t T e x t ( ) ) ) . d o u b l e V a l u e ( ) ) ;
d i n . setNmi ( (new I n t e g e r ( TextFieldNmi . g e t T e x t ( ) ) ) . i n t V a l u e ( ) ) ;
IMetodaTangentei o b j=new MetodaTangenteiWeb ( ) ;
DataOut dout=o b j . metodaTangentei ( d i n ) ;
DecimalFormat f=new DecimalFormat ( 0 . 0 0 0 0 0 E0 ) ;
S t r i n g s o l=f . f o r m a t ( dout . getX ( ) ) ;
S t r i n g v a l=f . f o r m a t ( dout . getF ( ) ) ;
T e x t F i e l d I n d . s e t T e x t ( (new I n t e g e r ( dout . g e t I n d ( ) ) ) . t o S t r i n g ( ) ) ;
T e x t F i e l d I t e r . s e t T e x t ( (new I n t e g e r ( dout . g e t N i ( ) ) ) . t o S t r i n g ( ) ) ;
TextFieldSol . setText ( s o l ) ;
TextFieldVal . setText ( val ) ;
T e x t F i e l d I n d . s e t V i s i b l e ( true ) ;
T e x t F i e l d S o l . s e t V i s i b l e ( true ) ;
T e x t F i e l d V a l . s e t V i s i b l e ( true ) ;
T e x t F i e l d I t e r . s e t V i s i b l e ( true ) ;
}
}));
g r i d p a n e . setVgap ( 8 ) ;
g r i d p a n e . setHgap ( 8 ) ;
gridpane . getChildren ( ) .
addAll ( labelVar , labelAprox , labelExpr , labelTol , labelNmi ) ;
gridpane . getChildren ( ) .
a d d A l l ( TextFieldVar , TextFieldAprox , TextFieldExpr , T e x t F i e l d T o l , TextFieldNmi ) ;
gridpane . getChildren ( ) .
addAll ( l a b e l I n d , l a b e l S o l , labelVal , l a b e l I t e r ) ;
gridpane . getChildren ( ) .
addAll ( TextFieldInd , TextFieldSol , TextFieldVal , T e x t F i e l d I t e r ) ;
g r i d p a n e . g e t C h i l d r e n ( ) . a d d A l l ( btn ) ;
r o o t . g e t C h i l d r e n ( ) . add ( g r i d p a n e ) ;

85

86

GRAFICA

CAPITOLUL 6. APLICAT
II CU INTERFAT
A

primaryStage . setScene ( scene ) ;


p r i m a r y S t a g e . show ( ) ;

116
117

118
119

Imaginea interfetei grafice completata cu datele problemei rezolvate n 1.2 mpreuna cu


rezultatele obtinute sunt prezentate n Fig. 6.1.

Fig. 6.1: Interfata grafica pentru rezolvarea ecuatiei algebrice.

6.2

Rezolvarea unui sistem algebric de ecuatii liniare

Rezolvarea unui sistem algebric Ax = b va utiliza extinderea mini-bibliotecii mathlib,


dezvoltata n 2.3. Rezolvarea se bazeaza pe functia Scilab linsolve.

6.2.1

Interfata grafic
a bazat
a pe Swing

In Netbeans, interfata grafica se construieste aproape n totalitate cu mouse-ul, codul


generandu-se n fundal. In consecinta se va prezenta doar codul specific aplicatiei, codul
pentru interfata grafica generata de Netbeans va fi omis, acest cod este dependent de
versiunea utilizata.
Interfata grafica este data n Fig. 6.2.

Clientul editeaza un fisier text cu coeficientii sistemului. Fiecare linie a acestui fisier
va contine coeficientii unei linii a sistemului iar ultimul element va fi termenul liber.
Separatorul este caracterul spatiu (blanc).
Dupa un clic pe butonul Incarca fisierul sistemului va apare fereastra pentru selectarea
fisierului cu datele sistemului (Fig. 6.3).

6.2. REZOLVAREA UNUI SISTEM ALGEBRIC DE ECUAT


II LINIARE

87

Fig. 6.2: Interfata grafica pentru rezolvarea sistemului.


Continutul fisierulului cu datele sistemului va fi preluat de aplicatie. Imediat se apeleaza rezolvarea sistemului algebric de ecuatii liniare. Rezultatele se afiseaza ntr-un control de tip JTextArea. Rezultatele din Fig. 6.4 corespund exemplului din 2.3.

Selectarea fisierului se programeaza utilizand controlul Swing JFileChooser. Schema de


prelucrare poate fi
JFileChooser fc=new JFileChooser();
fc.setDialogTitle(" titlu ");
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
try{
if (evt.getSource() == jButtonUpload){
int returnVal = fc.showOpenDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
// Prelucrarea fisierului
}
else{
throw new Exception("Actiune anulata de client.");
}
}
}
catch(Exception ex){
// prelucrarea exceptiei generate
}

Codul sursa (obtinut cu Netbeans) este


1
2
3

package l i n e a r ;
import j a v a x . swing . J F i l e C h o o s e r ;
import j a v a . i o . ;

88

GRAFICA

CAPITOLUL 6. APLICAT
II CU INTERFAT
A

Fig. 6.3: Fereastra de dialog pentru selectarea sistemului.

import m a t h l i b . c l i e n t . l i n e a r . ;
import m a t h l i b . c l i e n t . l i n e a r . impl . R e z o l v i t o r S c i l a b ;
import j a v a . t e x t . DecimalFormat ;

public c l a s s S i s t e m L i n i a r extends j a v a x . swing . JFrame {

4
5

10
11
12
14
15
16
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

public S i s t e m L i n i a r ( ) {
initComponents ( ) ;
}
private void i n i t C o m p o n e n t s ( ) {
// cod g e n e r a t de Netbeans
}
private void jButtonUploadMouseClicked ( j a v a . awt . e v e n t . MouseEvent e v t ) {
jTextFieldStatus . setText ( ) ;
J F i l e C h o o s e r f c=new J F i l e C h o o s e r ( ) ;
fc . setDialogTitle ( Alegeti f i s i e r u l sistemului );
f c . s e t F i l e S e l e c t i o n M o d e ( J F i l e C h o o s e r . FILES ONLY ) ;
DecimalFormat f=new DecimalFormat ( 0 . 0 0 0 0 E0 ) ;
jTextAreaSol . setText ( ) ;
try {
i f ( e v t . g e t S o u r c e ( ) == jButtonUpload ) {
i n t r e t u r n V a l = f c . showOpenDialog ( t h i s ) ;
i f ( r e t u r n V a l == J F i l e C h o o s e r .APPROVE OPTION) {
File f i l e = fc . getSelectedFile ();
F i l e I n p u t S t r e a m f i s =new F i l e I n p u t S t r e a m ( f i l e ) ;
InputStreamReader i s r =new InputStreamReader ( f i s ) ;
B u f f e r e d R e a d e r br=new B u f f e r e d R e a d e r ( i s r ) ;
DataIn d i n=new DataIn ( ) ;
d i n . s e t M a t r i x ( br ) ;
br . c l o s e ( ) ;
isr . close ();
f i s . close ();
I R e z o l v i t o r S c i l a b o b j=new R e z o l v i t o r S c i l a b ( ) ;
DataOut dout=o b j . r e z o l v i t o r S c i l a b ( d i n ) ;
S t r i n g r e z= ;
i f ( dout . i s C o m p a t i b i l ( ) ) {
double [ ] x=dout . getX ( ) ;

6.2. REZOLVAREA UNUI SISTEM ALGEBRIC DE ECUAT


II LINIARE

Fig. 6.4: Afisarea rezultatelor


double [ ] [ ] k=dout . getK ( ) ;
r e z=X=\n ;
i n t l=x . l e n g t h ;
f o r ( i n t i =0; i <l ; i ++){
r e z+=f . f o r m a t ( x [ i ] ) ;
r e z+= \n ;
}
r e z+= Ker=\n ;
i f ( k!= n u l l ) {
i n t c=k [ 0 ] . l e n g t h ;
f o r ( i n t i =0; i <l ; i ++){
f o r ( i n t j =0; j <c ; j ++){
r e z+=f . f o r m a t ( k [ i ] [ j ] ) ;
r e z+=
;
}
r e z+= \n ;
}
}
else {
r e z+= [ ] ;
}

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

}
else {
r e z= S i s t e m i n c o m p a t i b i l ! ;
}
jTextAreaSol . setText ( rez ) ;

64
65
66
67
68

}
else {
throw new E x c e p t i o n ( A c t i u n e a n u l a t a de c l i e n t . ) ;
}

69
70
71
72

}
}
catch ( E x c e p t i o n ex ) {
j T e x t F i e l d S t a t u s . s e t T e x t ( ex . g e t M e s s a g e ( ) ) ;
}

73
74
75
76
77
78

89

90

public s t a t i c void main ( S t r i n g a r g s [ ] ) {


j a v a . awt . EventQueue . i n v o k e L a t e r (new Runnable ( ) {
public void run ( ) {
new S i s t e m L i n i a r ( ) . s e t V i s i b l e ( true ) ;
}
});
}

80
81
82
83
84
85
86

private
private
private
private
private
private

88
89
90
91
92
93
94

GRAFICA

CAPITOLUL 6. APLICAT
II CU INTERFAT
A

j a v a x . swing . JButton jButtonUpload ;


j a v a x . swing . J L a b e l j L a b e l S o l ;
j a v a x . swing . JPanel j P a n e l 1 ;
j a v a x . swing . J S c r o l l P a n e j S c r o l l P a n e 1 ;
j a v a x . swing . JTextArea j T e x t A r e a S o l ;
j a v a x . swing . J T e x t F i e l d j T e x t F i e l d S t a t u s ;

Codul nereprodus genereaza interfata grafica din Fig. 6.2.

Capitolul 7
Generarea reprezent
arilor grafice
Afirmatia o imagine grafica spune mai multe decat o mie de cuvinte este adevarata n
numeroase cazuri - si cu siguranta cand rezultatele corespund valorilor unei functii.
Exista multe produse informatice care ofera functii pentru obtinerea de reprezentari
grafice.

7.1

PtPlot

O solutie simpla este data de produsul PtPlot, dezvoltat la Universitatea din California.
In cele ce urmeaza vom utiliza interfata de programare oferita (API) pentru generarea
graficului unei functii reale de variabila reala. Este nevoie de arhiva plotapplication.jar
aflata n catalogul ptolemy\plot din distributie.
Problema pe care dorim sa o rezolva este reprezentarea grafica a unei functii reale de
variabila reala.
Datele problemei sunt simbolul variabilei, expresia functiei si intervalul n care se
reprezinta functia. Acest interval poate sa nu fie inclus n domeniul de definitie al functiei.
Ideea reprezentarii este simpla: n intervalul dat, se considera o retea de puncte n care se
calculeaza valorile functiei. Generarea graficului este transparenta programatorului, fiind
efectuata de PtPlot. Rezultatul va fi un obiect java.awt.image.BufferedImage a carei
vizualizare cade n sarcina programatorului.
O problema consta n depistarea punctelor sau intervalelor n care functia nu este
definita.
Utilizarea resursele pachetului PtPlot se declara prin
import ptolemy.plot.*;

Reprezentarea grafica se va obtine prin intermediul unui obiect


Plot plotObj=new Plot();

Definim punctele intervalului [a, b] care urmeaza a fi reprezentate


h=(b-a)/n;
int dataset=0;
for(int i=0;i<=n;i++){
x=a+i*h;
y=f(x)

91

92

CAPITOLUL 7. GENERAREA REPREZENTARILOR


GRAFICE

if((Double.isInfinite(y))||(Double.isNaN(y))){
dataset++;
}
else{
plotObj.addPoint(dataset,x,y,true);
}
}

Punctele apartinand unui interval al domeniului de definitie sunt caracterizate printr-o


variabila ntreaga dataset. Doar aceste puncte vor fi unite de catre PtPlot. Acest lucru
este indicat prin valoarea true atribuita ultimei variabile a metodei addPoint.
Reprezentarea grafica este continuta ntr-o variabila de tip java.awt.image.Bufferd
Image si corespunde unui dreptunghi de rezolutie xDim yDim pixeli.
Rectangle rectangle=new Rectangle(xDim,yDim);
BufferedImage image=plotObj.exportImage(rectangle);

Metode ale clasei Plot (selectie)


setTitle(String title)
setXLabel(String xLabel )
setYLabel(String yLabel )
setSize(int xDim,int yDim)
setXRange(int a,int b)
setYRange(int c,int d)
setGrid(boolean grid )
setXLog(boolean log)
setYLog(boolean log)
setColor(boolean color )
addLegend(int dataset,String legenda)

Adauga titlul reprezentarii grafice.


Adauga eticheta axei Ox.
Adauga eticheta axei Oy.
Fixeaza rezolutia reprezentarii.
Fixeaza intervalul reprezentarii pe axa Ox.
Fixeaza intervalul reprezentarii pe axa Oy.
Pentru true se deseneaza o retea de drepte.
Pentru true axa Ox este logaritmica.
Pentru true axa Oy este logaritmica.
Pentru false graficul este alb/negru.
Adauga legenda setului de date dataset.

Redarea ntr-o fereastra a monitorului se obtine apeland


ShowImage si=new ShowImage(image,xDim,yDim);
si.show();

Codul programului ShowImage:


1
2
3
5
6
7
8

package p l o t 2 d ;
import j a v a . awt . ;
import j a v a x . swing . JFrame ;
public c l a s s ShowImage{
MyCanvas mc=n u l l ;
i n t xDim=0;
i n t yDim=0;
ShowImage ( Image image , i n t xDim , i n t yDim ) {
t h i s . xDim=xDim ;
t h i s . yDim=yDim ;
mc=new MyCanvas ( image ) ;
}
public void show ( ) {
JFrame j f r a m e = new JFrame ( G r a f i c u l f u n c t i e i ) ;
jframe . addNotify ( ) ;
j f r a m e . getContentPane ( ) . s e t L a y o u t (new BorderLayout ( ) ) ;
j f r a m e . getContentPane ( ) . add (mc , BorderLayout .CENTER) ;
j f r a m e . s e t S i z e ( xDim , yDim ) ;
j f r a m e . s e t V i s i b l e ( true ) ;
}

10
11
12
13
14
15
16
17
18
19
20
21
22
23

93

7.1. PTPLOT

unde MyCanvas este clasa


1
2
4
5

package p l o t 2 d ;
import j a v a . awt . ;
public c l a s s MyCanvas extends Canvas {
Image image=n u l l ;
MyCanvas ( Image image ) {
t h i s . image=image ;
}
@Override
public void p a i n t ( G r a p h i c s g ) {
g . drawImage ( image , 0 , 0 , t h i s ) ;
}

7
8
9
10
11
12
13
14

Exemplul 7.1.1 Program pentru reprezentarea grafica a unei functii.


Datele necesare se introduc prin intermediul unei interfete grafice (Fig. 7.1)

Fig. 7.1: Interfata grafica pentru datele graficului unei functii.

Codul programului cu interfata grafica Swing si care utilizeaza JEP pentru evaluarea
valorilor functiei data ca parametru de tip String este
1
2
3
4
5
7
8
9

package p l o t 2 d ;
import ptolemy . p l o t . ;
import o r g . nfunk . j e p . ;
import j a v a . awt . R e c t a n g l e ;
import j a v a . awt . image . B u f f e r e d I m a g e ;
public c l a s s G r a f i c extends j a v a x . swing . JFrame {
i n t xDim=500;
i n t yDim=300;

94

11
12
13
15
16
17
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
60
61
62
63
64
65
66
68
69
70
71
72
73
74
75
76

CAPITOLUL 7. GENERAREA REPREZENTARILOR


GRAFICE

public G r a f i c ( ) {
initComponents ( ) ;
}
private void i n i t C o m p o n e n t s ( ) {
// cod g e n e r a t de Netbeans
}
private void j B u t t o n P l o t M o u s e C l i c k e d ( j a v a . awt . e v e n t . MouseEvent e v t ) {
JEP p a r s e r=new JEP ( ) ;
p a r s e r . addStandardFunctions ( ) ;
p a r s e r . addStandardConstants ( ) ;
S t r i n g v a r=j T e x t F i e l d V a r . g e t T e x t ( ) ;
S t r i n g f c t=j T e x t F i e l d F c t . g e t T e x t ( ) ;
S t r i n g l e f t =j T e x t F i e l d I n f . g e t T e x t ( ) ;
parser . parseExpression ( l e f t ) ;
double a=p a r s e r . g e t V a l u e ( ) ;
S t r i n g r i g h t=j T e x t F i e l d S u p . g e t T e x t ( ) ;
parser . parseExpression ( right ) ;
double b=p a r s e r . g e t V a l u e ( ) ;
p a r s e r . a d d V a r i a b l e ( var , 0 ) ;
parser . parseExpression ( f c t ) ;
P l o t p l o t O b j=new P l o t ( ) ;
i n t n=xDim 8 ;
double h , x , y ;
i f ( b<a ) {
h=a ;
a=b ;
b=h ;
}
h=(ba ) / n ;
i n t d a t a s e t =0;
f o r ( i n t i =0; i <=n ; i ++){
x=a+i h ;
p a r s e r . a d d V a r i a b l e ( var , x ) ;
y=p a r s e r . g e t V a l u e ( ) ;
i f ( ( Double . i s I n f i n i t e ( y ) ) | | ( Double . isNaN ( y ) ) ) {
d a t a s e t ++;
}
else {
p l o t O b j . addPoint ( d a t a s e t , x , y , true ) ;
}
}
R e c t a n g l e r e c t a n g l e=new R e c t a n g l e ( xDim , yDim ) ;
B u f f e r e d I m a g e image=p l o t O b j . e x p o r t I m a g e ( r e c t a n g l e ) ;
ShowImage s i=new ShowImage ( image , xDim , yDim ) ;
s i . show ( ) ;
}
public s t a t i c void main ( S t r i n g a r g s [ ] ) {
j a v a . awt . EventQueue . i n v o k e L a t e r (new Runnable ( ) {
public void run ( ) {
new G r a f i c ( ) . s e t V i s i b l e ( true ) ;
}
});
}
private
private
private
private
private
private
private
private
private

j a v a x . swing . JButton j B u t t o n P l o t ;
j a v a x . swing . J L a b e l j L a b e l F c t ;
j a v a x . swing . J L a b e l j L a b e l I n f ;
j a v a x . swing . J L a b e l j L a b e l S u p ;
j a v a x . swing . J L a b e l j L a b e l V a r ;
j a v a x . swing . J T e x t F i e l d j T e x t F i e l d F c t ;
j a v a x . swing . J T e x t F i e l d j T e x t F i e l d I n f ;
j a v a x . swing . J T e x t F i e l d j T e x t F i e l d S t a t u s ;
j a v a x . swing . J T e x t F i e l d j T e x t F i e l d S u p ;

95

7.2. JFREECHART

private j a v a x . swing . J T e x t F i e l d j T e x t F i e l d V a r ;

77
78

Graficul obtinut pentru functia f (x) = x

x2 1, x [5, 5] este dat n Fig. 7.2.

Fig. 7.2: Rezultatul reprezentarii grafice.

7.2

jfreechart

In vederea compilarii este necesar ca variabila de sistem classpath sa contina referinta


la fisierul jfreechart-*.*.*.jar, dar pentru executie trebuie declarata si referinta la jcommon*.*.*.jar, aflata de asemenea n distributia produsului jfreechart.
jfreechart este destinat programatorilor, permitand generarea mai multor tipuri de
grafice 2D. Exemplificam prin reprezentarea grafica a unei functii reale de variabila reala.
Reprezentarile grafice se obtin prin intermediul obiectelor de tip JFreeChart. Un
asemenea obiect se instantiaza prin metode statice ale clasei ChartFactory.
Metoda statica prin care se creaza o reprezentare 2D unind punctele consecutive prin
segmente este
public static JFreeChart createXYLineChart(java.lang.String title,
java.lang.String xAxisLabel,
java.lang.String yAxisLabel,
XYDataset dataset,
PlotOrientation orientation,
boolean legend,
boolean tooltips,
boolean urls)
unde
title este numele reprezentarii grafice;

96

CAPITOLUL 7. GENERAREA REPREZENTARILOR


GRAFICE

xAxisLabel si yAxisLabel sunt etichetele axelor Ox, respectiv Oy;


dataset contine una sau mai multe obiecte de tip XYSeries. Un obiect de tip
XYSeries nmagazineaza un sir de puncte, fixate prin coordonatele carteziene (xi , yi )i .
Pentru fiecare asemenea obiect, se reprezinta punctele unite prin segmente de dreapta;
legend indicator al prezentei unei legende.
Denumim aceasta reprezentare prin XYLineChart.
Pentru a obtine obiectul dataset, ce implementeaza interfata XYDataset se poate proceda dupa cum urmeaza:
1. Se instantiaza un obiect de tip XYSeries
XYSeries serie=new XYSeries(id )
unde id este un String, reprodus n legenda, prin care se identifica graficul corespunzator seriei de puncte.
2. Se completeaza variabila serie cu coordonatele punctelor
for(int i=0;i<n;i++){
double x=. . .
double y=. . .
serie.add(x,y);
}

3. Se instantiaza variabila dataset prin


XYDataset dataset=new XYSeriesCollection(serie);
Cu metoda clasei XYSeriesCollection
void addSeries(XYSeries serie),
se pot adauga alte serii de date.
Astfel prelucrarea este
XYSeries serie=new XYSeries(f(x));
for(int i=0;i<n;i++){
double x=. . .
double y=. . .
serie.add(x,y);
}
XYDataset dataset=new XYSeriesCollection(series);
JFreeChart chart=ChartFactory(title,x,y,dataset,true,false,false);

Odata obiectul de chart tip JFreeChart creat, putem:


obtine un obiect de tip java.awt.image.BufferedImage care poate fi desenat ntrun obiect de tip java.awt.Canvas:
BufferedImage image=chart.createBufferedImage( xDim, yDim);
xDim yDim reprezentand rezolutia imaginii.
Din nou programul ShowImage afiseaza imaginea obtinuta pe ecranul monitorului.

7.2. JFREECHART

97

salva imaginea n format PNG sau JPEG ntr-un fisier


ChartUtilities.saveChartAsPNG(new java.io.File(numeFisier ), chart, xDim,
yDim);
Exemplul 7.2.1 Program pentru reprezentarea grafica a unei functii.
Datele necesare se introduc prin intermediul aceleiasi interfete grafice (Fig. 7.1)
Daca a, b corespund marginilor inferioara si respectiv superioara a intervalului n
care se cere reprezentarea functiei f (x), atunci ideea reprezentarii consta din construirea sirului de puncte de coordonate (xi , yi )0in cu xi = a + i ba
, yi = f (xi ), n N si
n
de reprezentarea lor print-un grafic XYLineChart.

Pentru exemplul introdus f (x) = x x2 1, domeniul de definitie este (, 1]


[1, ) si n consecinta graficul este alcatuit din doua componente.
Evaluarea functiei n punctele ce nu apartin domeniului de definitie produce una din
constantele Double.POSITIVE(NEGATIVE) INFINITY sau Double.NaN, valori care nu se
vor nregistra n obiectul XYSeries.
In acest caz reprezentarea XYLineChart este neconvenabila - punctele de coordonate
(-1,-1) si (1,1) ar fi unite printr-un segment. Pentru depasirea acestui inconvenient definim
o reprezentare XYDiscontinuousChart prin metoda
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

public JFreeChart c r e a t e X Y D i s c o n t i n u o u s C h a r t ( S t r i n g t i t l e ,
S t r i n g xAx isLa bel ,
S t r i n g yAx isLa bel ,
XYDataset d a t a s e t ,
PlotOrientation orientation ,
boolean l e g e n d ,
boolean t o o l t i p s ,
boolean u r l s ) {
NumberAxis xAxis = new NumberAxis ( x A x i s L a b e l ) ;
xAxis . s e t A u t o R a n g e I n c l u d e s Z e r o ( f a l s e ) ;
NumberAxis yAxis = new NumberAxis ( y A x i s L a b e l ) ;
XYItemRenderer r e n d e r e r =
new StandardXYItemRenderer ( StandardXYItemRenderer . DISCONTINUOUS LINES ) ;
XYPlot p l o t = new XYPlot ( d a t a s e t , xAxis , yAxis , r e n d e r e r ) ;
plot . setOrientation ( orientation ) ;
i f ( t o o l t i p s ){
r e n d e r e r . s e t B a s e T o o l T i p G e n e r a t o r (new StandardXYToolTipGenerator ( ) ) ;
}
i f ( u r l s ){
r e n d e r e r . setURLGenerator (new StandardXYURLGenerator ( ) ) ;
}
JFreeChart c h a r t=
new JFreeChart ( t i t l e , new Font ( S a n s S e r i f , Font .BOLD, 1 8 ) , p l o t , l e g e n d ) ;
return c h a r t ;
}

Aceasta reprezentare se utilizeaza doar daca numarul componentelor este cel putin 2.
Pentru exemplul dat, va rezulta imaginea din Fig. 7.3

Codul sursa al programului este:


1
2
3

package p l o t 2 d ;
import o r g . j f r e e . c h a r t . ;
import o r g . j f r e e . data . xy . ;

98

CAPITOLUL 7. GENERAREA REPREZENTARILOR


GRAFICE

Fig. 7.3: Rezultatul reprezentarii grafice.


4
5
6
7
8
9
10
11
13
14
15
17
18
19
21
22
23
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

import
import
import
import
import
import
import
import

o r g . j f r e e . c h a r t . r e n d e r e r . xy . ;
org . j f r e e . chart . p l o t . ;
org . j f r e e . chart . a x i s . ;
org . j f r e e . chart . l a b e l s . ;
org . j f r e e . chart . u r l s . ;
j a v a . awt . ;
j a v a . awt . image . ;
o r g . nfunk . j e p . ;

public c l a s s G r a f i c extends j a v a x . swing . JFrame {


i n t xDim=500;
i n t yDim=300;
public G r a f i c ( ) {
initComponents ( ) ;
}
private void i n i t C o m p o n e n t s ( ) {
// cod g e n e r a t de Netbeans c o r e s p u n z a t o a r e i n t e r f a t e i g r a f i c e
}
private void j B u t t o n P l o t M o u s e C l i c k e d ( j a v a . awt . e v e n t . MouseEvent e v t ) {
JEP p a r s e r=new JEP ( ) ;
p a r s e r . addStandardFunctions ( ) ;
p a r s e r . addStandardConstants ( ) ;
S t r i n g v a r=j T e x t F i e l d V a r . g e t T e x t ( ) ;
S t r i n g f c t=j T e x t F i e l d F c t . g e t T e x t ( ) ;
S t r i n g l e f t =j T e x t F i e l d I n f . g e t T e x t ( ) ;
parser . parseExpression ( l e f t ) ;
double a=p a r s e r . g e t V a l u e ( ) ;
S t r i n g r i g h t=j T e x t F i e l d S u p . g e t T e x t ( ) ;
parser . parseExpression ( right ) ;
double b=p a r s e r . g e t V a l u e ( ) ;
p a r s e r . a d d V a r i a b l e ( var , 0 ) ;
parser . parseExpression ( f c t ) ;
XYSeries s e r i e s = new XYSeries ( y ) ;
i n t n=xDim 8 ;

99

7.2. JFREECHART

byte [ ] s=new byte [ n + 1 ] ;


double h , x , y ;
i f ( b<a ) {
h=a ;
a=b ;
b=h ;
}
h=(ba ) / n ;
f o r ( i n t i =0; i <=n ; i ++){
x=a+i h ;
p a r s e r . a d d V a r i a b l e ( var , x ) ;
y=p a r s e r . g e t V a l u e ( ) ;
i f ( ( Double . i s I n f i n i t e ( y ) ) | | ( Double . isNaN ( y ) ) ) {
s [ i ]=1;
}
else {
s e r i e s . add ( x , y ) ;
s [ i ]=0;
}
}
XYDataset d a t a s e t = new X Y S e r i e s C o l l e c t i o n ( s e r i e s ) ;
JFreeChart c h a r t=n u l l ;
i f ( isCompact ( s ) ) {
c h a r t = C h a r t F a c t o r y . createXYLineChart (
G r a f i c u l f u n c t i e i , x , y ,
d a t a s e t , o r g . j f r e e . c h a r t . p l o t . P l o t O r i e n t a t i o n . VERTICAL,
true , f a l s e , f a l s e ) ;
}
else {
chart = createXYDiscontinuousChart (
G r a f i c u l f u n c t i e i , x , y ,
d a t a s e t , o r g . j f r e e . c h a r t . p l o t . P l o t O r i e n t a t i o n . VERTICAL,
true , f a l s e , f a l s e ) ;
}
B u f f e r e d I m a g e image=c h a r t . c r e a t e B u f f e r e d I m a g e ( xDim , yDim ) ;
ShowImage s i=new ShowImage ( image , xDim , yDim ) ;
s i . show ( ) ;
try {
C h a r t U t i l i t i e s . saveChartAsPNG (new j a v a . i o . F i l e ( F u n c t i a . png ) ,
c h a r t , xDim , yDim ) ;
}
catch ( j a v a . i o . IOException e ) {
System . e r r . p r i n t l n ( E r r o r w r i t i n g image t o f i l e : +
e . getMessage ( ) ) ;
}

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

88

public JFreeChart c r e a t e X Y D i s c o n t i n u o u s C h a r t ( . .

90

boolean isCompact ( byte [ ] s ) {


i n t n=s . l e n g t h ;
i n t noNaN=0 , no =0;
boolean f i r s t =true ;
f o r ( i n t i =0; i <n ; i ++){
i f ( ( s [ i ]==0)&& f i r s t ) {
f i r s t =f a l s e ;
no++;
}
i f ( ( s [ i ]==1)&& ( ! f i r s t ) ) noNaN++;
i f ( ( s [ i ]==0)&& ( ! f i r s t ) && ( noNaN>=1)) {
no++;
break ;
}
}
i f ( no >1)
return f a l s e ;
else

91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

.){.

. .}

100

CAPITOLUL 7. GENERAREA REPREZENTARILOR


GRAFICE

return true ;

108
109

111

public s t a t i c void main ( S t r i n g a r g s [ ] ) {


j a v a . awt . EventQueue . i n v o k e L a t e r (new Runnable ( ) {
public void run ( ) {
new G r a f i c ( ) . s e t V i s i b l e ( true ) ;
}
});
}

112
113
114
115
116
117

private
private
private
private
private
private
private
private
private
private

119
120
121
122
123
124
125
126
127
128
129

j a v a x . swing . JButton j B u t t o n P l o t ;
j a v a x . swing . J L a b e l j L a b e l F c t ;
j a v a x . swing . J L a b e l j L a b e l I n f ;
j a v a x . swing . J L a b e l j L a b e l S u p ;
j a v a x . swing . J L a b e l j L a b e l V a r ;
j a v a x . swing . J T e x t F i e l d j T e x t F i e l d F c t ;
j a v a x . swing . J T e x t F i e l d j T e x t F i e l d I n f ;
j a v a x . swing . J T e x t F i e l d j T e x t F i e l d S t a t u s ;
j a v a x . swing . J T e x t F i e l d j T e x t F i e l d S u p ;
j a v a x . swing . J T e x t F i e l d j T e x t F i e l d V a r ;

7.3

VisAD

VisAD Visualization for Algorithmic Development este un pachet Java, care permite obtinerea de reprezentari grafice n doua (2D) si trei dimensiuni (3D), de animatii,
ftp://ftp.ssec.wisc.edu/pub/visad-2.0/visad.jar. La dezvoltarea pachetului au
contribuit mai multe universitati si institutii, ncepand din 1992. VisAD se bazeaza
pe un model de reprezentare prin obiecte a diverselor entitati ce apar n construirea unei
reprezentari grafice. Fixarea datelor de reprezentat grafic, care apar uzual ntr-o formulare
matematica, n obiectele modelului este relativ simpla si cade n sarcina programatorului,
la fel si fixarea unor parametri privind modul de afisare. Toate operatiile care conduc la
imaginea grafica sunt complet transparente programatorului.
Utilizarea produsului necesita n plus softul java3d de la Oracle.
Ierarhia de clase Java care fixeaza structurile de date utilizabile n VisAD este
MathType
|
----------------------------------------------------|
|
|
|
ScalarType
TupleType
SetType
FunctionType
|
|
---------RealTupleType
|
|
RealType TextType
Dintre aceste clase precizam:
RealType serveste la declararea unei variabile numerice.
Instantierea unui obiect se programeaza prin metoda statica

7.3. VISAD

101

RealType getRealType(String numeVar )


RealTupleType serveste la declararea de variabile din Rn . Constructori:
RealTupleType(RealType[])
RealTupleType(RealType,RealType)
FunctionType serveste la declararea functiilor, avand constructorul
FunctionType(MathType domDef ,MathType multimeVal )
In urmatoarele doua exemple introducem si alte clase ale pachetului VisAD care intervin
la construirea unei reprezentari grafice si aratam un sablon de lucru.

Reprezentarea grafic
a a unei functii de o variabil
a
Construirea reprezentarii grafice a unei functii f ct : [a, b]D R se obtine parcurgand
pasii:
1. Definirea structurilor de date
RealType xType = RealType.getRealType("x");
RealType yType = RealType.getRealType("y");
FunctionType fctType = new FunctionType(xType, yType);
2. Precizarea datelor: n intervalul [a, b] se defineste o retea echidistanta de n N
puncte
Linear1DSet xSet = new Linear1DSet(xType, a, b, n);
Tabloul absciselor este generat prin
float[][] xValues=xSet.getSamples(true);
iar multimea valorilor functiei se calculeaza prin
double[][] yValues = new double[1][n];
for(int i=0;i<n;i++){
yValues[0][i]=fct(xValues[0][i]);
}
3. Fixarea conexiunii dintre structurile de date si tablourile de valori
FlatField ff = new FlatField( fctType, xSet);
ff.setSamples( yValues );
4. Fixarea elementelor care definesc reprezentarea grafica

102

CAPITOLUL 7. GENERAREA REPREZENTARILOR


GRAFICE

Structurile de date:
ScalarMap xMap = new ScalarMap( xType, Display.XAxis );
ScalarMap yMap = new ScalarMap( yType, Display.YAxis );
Conexiunea dintre structurile de date si tablourile de valori
DataReferenceImpl dri=new DataReferenceImpl("data_ref");
dri.setData(ff);
5. Definirea unui container grafic caruia i se adauga elementele reprezentarii grafice
DisplayImpl display = new DisplayImplJ2D("2d");
display.addMap( xMap );
display.addMap( yMap );
display.addReference(dri);
6. Optional, reprezintarea axelor se programeaza prin
GraphicsModeControl
gmc=(GraphicsModeControl)display.getGraphicsModeControl();
gmc.setScaleEnable(true);
7. Containerul grafic se integreaza ntr-un cadru swing
JFrame jframe = new JFrame();
jframe.getContentPane().add(display.getComponent(),
BorderLayout.CENTER);

Exemplul 7.3.1 Sa se reprezinte graficul functiei f ct(x) = x x2 1, x [5, 5] \


(1, 1).
Pentru simplitate, datele problemei sunt fixate n clasa DataIn
1
2
3
4
5

package g r a f i c 2 d ;
public c l a s s DataIn {
private double a=5;
private double b=5;
private i n t n =100;
public double f c t ( double x ) {
return xMath . s q r t ( xx 1);
}

7
8
9

public double getA ( ) {


return a ;
}

11
12
13

public double getB ( ) {


return b ;
}

15
16
17

public i n t getN ( ) {
return n ;
}

19
20
21
22

7.3. VISAD

Reprezentarea grafica se genereaza n clasa


1
2
3
4
5
6
8
9
11
12
13
15
16
17
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

package g r a f i c 2 d ;
import v i s a d . ;
import v i s a d . j a v a 2 d . DisplayImplJ2D ;
import j a v a . rmi . RemoteException ;
import j a v a . awt . ;
import j a v a x . swing . ;
public c l a s s R e p r e z e n t a r e F u n c t i e 2 D {
private DataIn d i n ;
public R e p r e z e n t a r e F u n c t i e 2 D ( DataIn d i n ) {
t h i s . d i n=d i n ;
}
public void p l o t ( ) {
i n t n=d i n . getN ( ) ;
D i s p l a y I m p l d i s p l a y=n u l l ;
try {
// D e f i n i r e a s t r u c t u r i l o r de d a t e
RealType xType = RealType . getRealType ( x ) ;
RealType yType = RealType . getRealType ( y ) ;
FunctionType f c t T y p e = new FunctionType ( xType , yType ) ;
// P r e c i z a r e a d a t e l o r
L i n e a r 1 D S e t x S e t = new L i n e a r 1 D S e t ( xType , d i n . getA ( ) , d i n . getB ( ) , n ) ;
f l o a t [ ] [ ] x V al u e s=x S e t . g e t S a m p l e s ( true ) ;
double [ ] [ ] y V al u e s = new double [ 1 ] [ n ] ;
f o r ( i n t i =0; i <n ; i ++){
y Va l u es [ 0 ] [ i ]= d i n . f c t ( x V a lu e s [ 0 ] [ i ] ) ;
}
// F i x a r e a c o n e x i u n i i d i n t r e s t r u c t u r i l e de d a t e
// s i t a b l o u r i l e de v a l o r i
F l a t F i e l d f f = new F l a t F i e l d ( fctType , x S e t ) ;
f f . s e t S a m p l e s ( y Va l u es ) ;
// F i x a r e a e l e m e n t e l o r c a r e d e f i n e s c r e p r e z e n t a r e g r a f i c a
ScalarMap xMap = new ScalarMap ( xType , D i s p l a y . XAxis ) ;
ScalarMap yMap = new ScalarMap ( yType , D i s p l a y . YAxis ) ;
D a t a R e f e r e n c e I m p l d r i=new D a t a R e f e r e n c e I m p l ( d a t a r e f ) ;
d r i . setData ( f f ) ;
// D e f i n i r e a c o n t a i n e r u l u i g r a f i c e c a r u i a i
// s e adauga e l e m e n t e l e r e p r e z e n t a r i i g r a f i c e
d i s p l a y = new DisplayImplJ2D ( 2d ) ;
d i s p l a y . addMap ( xMap ) ;
d i s p l a y . addMap ( yMap ) ;
d i s p l a y . addReference ( d r i ) ;
// Desenarea a x e l o r de c o o r d o n a t e
GraphicsModeControl gmc=
( GraphicsModeControl ) d i s p l a y . g e t G r a p h i c s M o d e C o n t r o l ( ) ;
gmc . s e t S c a l e E n a b l e ( true ) ;
}
catch ( VisADException e ) {
System . out . p r i n t l n ( V i s a d E x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;
System . e x i t ( 1 ) ;
}
catch ( RemoteException e ) {
System . out . p r i n t l n ( RMIRemoteException : +e . g e t M e s s a g e ( ) ) ;
System . e x i t ( 1 ) ;
}
// I n t e g r a r e a i n t r un c a d r u l s w i n g
JFrame j f r a m e = new JFrame ( G r a f i c u l f u n c t i e i ) ;
j f r a m e . getContentPane ( ) . s e t L a y o u t (new BorderLayout ( ) ) ;
j f r a m e . getContentPane ( ) . add ( d i s p l a y . getComponent ( ) , BorderLayout .CENTER) ;
j f r a m e . s e t D e f a u l t C l o s e O p e r a t i o n ( j f r a m e . EXIT ON CLOSE ) ;
jframe . s e t S i z e (400 , 400);

103

104

CAPITOLUL 7. GENERAREA REPREZENTARILOR


GRAFICE

j f r a m e . s e t V i s i b l e ( true ) ;

66
67

69

public s t a t i c void main ( S t r i n g [ ] a r g s ) {


DataIn d i n=new DataIn ( ) ;
R e p r e z e n t a r e F u n c t i e 2 D o b j=new R e p r e z e n t a r e F u n c t i e 2 D ( d i n ) ;
obj . plot ( ) ;
}

70
71
72
73
74

Va rezulta imaginea din Fig. 7.4

Fig. 7.4: Graficul 2D produs de VisAD.

Reprezentarea grafic
a a unei functii de dou
a variabile
Procedam asemanator pentru construirea reprezentarii grafice a unei functii f ct :
([xM in , xM ax ] [yM in , yM ax ]) D R:
1. Definirea structurilor de date
RealType yType = RealType.getRealType("y");

105

7.3. VISAD

RealType zType = RealType.getRealType("z");


RealTupleType xyType = new RealTupleType(xType,yType);
FunctionType fctType = new FunctionType(xyType, zType);
2. Precizarea datelor: n dreptunghiul [xM in , xM ax ] [yM in , yM ax ] se defineste o retea
bidimensionala de puncte echidistante, n numar de nx ny
Linear2DSet xySet =
new Linear2DSet(xyType,XMin(),XMax(),nx,YMin(),YMax(),ny);
Tabloul punctelor este generat prin
float[][] xyValues=xySet.getSamples(true);
iar multimea valorilor functiei se calculeaza prin
double[][] zValues = new double[1][nx*ny];
for(int i=0;i<nx*ny;i++){
zValues[0][i]=din.fct(xyValues[0][i],xyValues[1][i]);
}
3. Fixarea conexiunii dintre structurile de date si tablourile de valori
FlatField ff = new FlatField(fctType, xySet);
ff.setSamples( zValues);
4. Fixarea elementelor care definesc reprezentarea grafica
Structurile de date:
ScalarMap
ScalarMap
ScalarMap
ScalarMap

xMap = new ScalarMap(xType, Display.XAxis );


yMap = new ScalarMap(yType, Display.YAxis );
zMap = new ScalarMap(zType, Display.ZAxis );
zColMap = new ScalarMap(zType, Display.RGB);

Ultimul rand are ca efect afisarea n culori a suprafetei, punctele cu valori mici
ale lui z se reprezinta n albastru iar cele cu valori mari n rosu.
Conexiunea dintre structurile de date si tablourile de valori
DataReferenceImpl dri=new DataReferenceImpl("data_ref");
dri.setData(ff);
5. Definirea unui container grafic caruia i se adauga elementele reprezentarii grafice

106

CAPITOLUL 7. GENERAREA REPREZENTARILOR


GRAFICE

DisplayImpl display = new DisplayImplJ3D("3d");


display.addMap( xMap );
display.addMap( yMap );
display.addMap( zMap );
display.addMap( zColMap );
display.addReference(dri);
6. Optional, reprezentarea axelor se programeaza prin
GraphicsModeControl
gmc=(GraphicsModeControl)display.getGraphicsModeControl();
gmc.setScaleEnable(true);
gmc.setTextureEnable(false);
7. Containerul grafic se integreaza ntr-un cadru swing
JFrame jframe = new JFrame();
jframe.getContentPane().add(display.getComponent(),
BorderLayout.CENTER);
Exemplul 7.3.2 Sa se reprezinte graficul functiei f ct(x, y) = xxyy, x [5, 5], y
[5, 5].
Din nou se fixeaza datele problemei n clasa DataIn
1
2
3
4
5
6
7
8
10
11
12
14
15
16
18
19
20
22
23
24
26
27
28
30
31

package g r a f i c 3 d ;
public c l a s s DataIn {
private double xMin=5;
private double xMax=5;
private double yMin=5;
private double yMax=5;
private i n t nx =30;
private i n t ny =30;
public double f c t ( double x , double y ) {
return xxyy ;
}
public double getXMin ( ) {
return xMin ;
}
public double getXMax ( ) {
return xMax ;
}
public double getYMin ( ) {
return yMin ;
}
public double getYMax ( ) {
return yMax ;
}
public i n t getNx ( ) {
return nx ;

7.3. VISAD

32

34

public i n t getNy ( ) {
return ny ;
}

35
36
37

Programul reprezentarii grafice are codul


1
2
3
4
5
6
8
9
11
12
13
15
16
17
18
20
21
22
23
24
25
26
28
29
30
31
32
33
34
35
37
38
39
40
42
43
44
45
46
47
48
50
51
52
53
54
55
56
57

package g r a f i c 3 d ;
import v i s a d . ;
import v i s a d . j a v a 3 d . DisplayImplJ3D ;
import j a v a . rmi . RemoteException ;
import j a v a . awt . ;
import j a v a x . swing . ;
public c l a s s R e p r e z e n t a r e F u n c t i e 3 D {
private DataIn d i n ;
public R e p r e z e n t a r e F u n c t i e 3 D ( DataIn d i n ) {
t h i s . d i n=d i n ;
}
public void plot3D ( ) {
i n t nx=d i n . getNx ( ) ;
i n t ny=d i n . getNy ( ) ;
D i s p l a y I m p l d i s p l a y=n u l l ;
try {
// D e f i n i r e a s t r u c t u r i i de d a t e
RealType xType = RealType . getRealType ( x ) ;
RealType yType = RealType . getRealType ( y ) ;
RealType zType = RealType . getRealType ( z ) ;
RealTupleType xyType = new RealTupleType ( xType , yType ) ;
FunctionType f c t T y p e = new FunctionType ( xyType , zType ) ;
// P r e c i z a r e a d a t e l o r
L i n e a r 2 D S e t xySet=new L i n e a r 2 D S e t ( xyType , d i n . getXMin ( ) , d i n . getXMax ( ) ,
nx , d i n . getYMin ( ) , d i n . getYMax ( ) , ny ) ;
f l o a t [ ] [ ] xyValues=xySet . g e t S a m p l e s ( true ) ;
double [ ] [ ] z V a l u e s = new double [ 1 ] [ nxny ] ;
f o r ( i n t i =0; i <nxny ; i ++){
z V a l u e s [ 0 ] [ i ]= d i n . f c t ( xyValues [ 0 ] [ i ] , xyValues [ 1 ] [ i ] ) ;
}
// F i x a r e a c o n e x i u n i i d i n t r e s t r u c t u r i l e de d a t e
// s i t a b l o u r i l e de v a l o r i
F l a t F i e l d f f = new F l a t F i e l d ( fctType , xySet ) ;
f f . setSamples ( zValues ) ;
// F i x a r e a e l e m e n t e l o r c a r e d e f i n e s c r e p r e z e n t a r e g r a f i c a
ScalarMap xMap = new ScalarMap ( xType , D i s p l a y . XAxis ) ;
ScalarMap yMap = new ScalarMap ( yType , D i s p l a y . YAxis ) ;
ScalarMap zMap = new ScalarMap ( zType , D i s p l a y . ZAxis ) ;
ScalarMap zColMap = new ScalarMap ( zType , D i s p l a y .RGB) ;
D a t a R e f e r e n c e I m p l d r i=new D a t a R e f e r e n c e I m p l ( d a t a r e f ) ;
d r i . setData ( f f ) ;
// D e f i n i r e a c o n t a i n e r u l u i g r a f i c e c a r u i a i
// s e adauga e l e m e n t e l e r e p r e z e n t a r i i g r a f i c e
d i s p l a y = new DisplayImplJ3D ( 3d ) ;
d i s p l a y . addMap ( xMap ) ;
d i s p l a y . addMap ( yMap ) ;
d i s p l a y . addMap ( zMap ) ;
d i s p l a y . addMap ( zColMap ) ;
d i s p l a y . addReference ( d r i ) ;

107

108

CAPITOLUL 7. GENERAREA REPREZENTARILOR


GRAFICE

// Elemente s u p l i m e n t a r e de c o n t r o l
GraphicsModeControl gmc=
( GraphicsModeControl ) d i s p l a y . g e t G r a p h i c s M o d e C o n t r o l ( ) ;
gmc . s e t S c a l e E n a b l e ( true ) ;
gmc . s e t T e x t u r e E n a b l e ( f a l s e ) ;

59
60
61
62
63

}
catch ( VisADException e ) {
System . out . p r i n t l n ( V i s a d E x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;
System . e x i t ( 1 ) ;
}
catch ( RemoteException e ) {
System . out . p r i n t l n ( RMIRemoteException : +e . g e t M e s s a g e ( ) ) ;
System . e x i t ( 1 ) ;
}

64
65
66
67
68
69
70
71
72

// I n t e g r a r e a i n t r un cadru s w i n g
JFrame j f r a m e=new JFrame ( G r a f i c u l 3D a l u n e i f u n c t i i i n 2 v a r i a b i l e ) ;
j f r a m e . getContentPane ( ) . s e t L a y o u t (new BorderLayout ( ) ) ;
j f r a m e . getContentPane ( ) . add ( d i s p l a y . getComponent ( ) , BorderLayout .CENTER) ;
j f r a m e . s e t D e f a u l t C l o s e O p e r a t i o n ( j f r a m e . EXIT ON CLOSE ) ;
jframe . s e t S i z e (600 , 600);
j f r a m e . s e t V i s i b l e ( true ) ;

74
75
76
77
78
79
80

}
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
DataIn d i n=new DataIn ( ) ;
R e p r e z e n t a r e F u n c t i e 3 D o b j=new R e p r e z e n t a r e F u n c t i e 3 D ( d i n ) ;
o b j . plot3D ( ) ;
}

81
82
83
84
85
86
87

Va rezulta imaginea din Fig. 7.5.

Imaginea reprodusa este dupa rotirea cu ajutorul mouse-ului a imaginii generata initial.

7.4

Vizualizarea functiilor complexe

Ne propunem vizualizarea functiei compleze f : D C C unde D = {z = x + iy :


x [xm , xM ], y [ym , yM ]}. Ideea vizualizarii, potrivit [8], consta n atribuirea unei culori
fiecarui numar complex. Pentru un punct z D se calculeaza f (z), acestuia i corespunde
o culoare C, iar vizualizarea functiei se obtine afisand punctul z n culoarea C.
O imagine grafica se va obtine ntr-o fereastra a ecranului
D = {0, 1, . . . , P } {0, 1, . . . , Q},

P, Q N.

Functia bijectiva : D D definita prin






xM xm
yM ym
(p, q) = xm +
p + i yM
q
P
Q
atribuie fiecarui pixel (p, q) D un numar complex din D, Fig. 7.6. Culoarea C
corespunzatoare numarului complex f ((p, q)) va fi atribuita pixelului de coordonate
(p, q), p {0, 1, . . . , P }, p {0, 1, . . . , Q}. In felul acesta se obtine vizualizarea functiei
complexe f.

7.4. VIZUALIZAREA FUNCT


IILOR COMPLEXE

Fig. 7.5: Graficul 3D produs de VisAD.

109

110

CAPITOLUL 7. GENERAREA REPREZENTARILOR


GRAFICE

'

z
6

D XXX
yM
XXX
X

X
a
XX
XXX
XX
XXX
D
Xz
X

ym

?
&

xm

xM

Fig. 7.6: Transformarea : D D.

Cubul culorilor
O culoare se formeaza dintr-un triplet (r, g, b) [0, 1]3 . Interpretam multimea [0, 1]3
ca un cub ale carui varfuri definesc culorile potrivit Fig. 7.7.
In Java, atribuirea unei culori (r, g, b) unui pixel (p, q) se programeaza prin
graphics.setColor(new Color(r,g,b));
graphics.fillRect(p,q,1,1);

unde graphics este un obiect de tip java.awt.Graphics atasat mediului (virtual) de


desenare, de exemplu
BufferedImage bi=new BufferedImage(P,Q,BufferedImage.TYPE_3BYTE_BGR);
Graphics graphics=bi.getGraphics();

Proiectia stereografic
a
Proiectia stereografica realizeaza o bijectie ntre planul complex completat cu elementul si suprafata S a sferei cu centrul n origine si de raza 1
S:

X 2 + Y 2 + Z 2 = 1.

Numarului complex z = x + iy i se asociaza punctul N, intersectia dreptei definita de


punctele M (x, y, 0) si A(0, 0, 1) cu sfera S, Fig. 7.8.
Ecuatiile dreptei AM sunt Xx = Yy = Z1
. Intersectia dreptei AM cu sfera S are
1
coordonatele
XN =

x2

2x
,
+ y2 + 1

YN =

x2

2y
,
+ y2 + 1

ZN = 1

x2

2
.
+ y2 + 1

111

7.4. VIZUALIZAREA FUNCT


IILOR COMPLEXE

6
b

albastru

cyan

magenta

alb
gverde

negru
rosu
r

galben

(r, g, b)
(0,0,0)
(1,0,0)
(0,1,0)
(0,0,1)
(1,1,0)
(1,0,1)
(0,1,1)
(1,1,1)

Culoarea
negru
rosu
verde
albastru
galben
magenta
cyan
alb

Fig. 7.7: Cubul culorilor.


p
Daca |z| = x2 + y 2 > 1 atunci intersectia se afla pe semisfera superioara, iar daca
|z| < 1 atunci intersectia se afla pe semisfera inferioara. Elementului i corespunde
punctul A, iar lui 0 i corespunde punctul diametral opus lui A.
Ideea atribuirii unei culori numarului complex z, adica a transformarii coordonatelor
proiectiei stereografice ntr-un punct al cubului [0, 1]3 consta din urmatoarele operatii:
1. O omotetie de centru O de factor 21 , care transforma sfera S ntr-o sfera de raza 21 ;
2. O rotatie ce duce axa OZ pe directia negru,alb;
3. O translatie ce duce centrul sferei n punctul de coordonate ( 12 , 12 , 12 ).
Procedand n acest fel, culorile alb si negru nu sunt atribuite nici unui punct, mai mult
dispersia culorilor este redusa. Pentru a remedia acest lucru, modificam valoarea lui Z.
Mai precis, Z va fi cota corespunzatoare punctului


2x
2x
,
,0
x2 + y 2 + 1 x2 + y 2 + 1

pe conul avand ca baza cercul X 2 +Y 2 = 1, Z = 0 si varful V (0, 0, 3) - n cazul punctului

de pe semisfera superioara, respectiv, conul cu aceasi baza dar cu varful V 0 (0, 0, 3) n cazul punctului de pe semisfera inferioara.
O dreapta care trece prin V


X = (Z 3)
(7.1)
Y = (Z 3)

112

CAPITOLUL 7. GENERAREA REPREZENTARILOR


GRAFICE

Proiectia stereografica

Constructia
pentru modificarea lui Z.
Fig. 7.8:

este generatoare a conului daca intersecteaza cercul bazei. Rezulta conditia de compatibilitate
3(2 + 2 ) = 1.
(7.2)
Eliminand parametrii si ntre relatiile (7.1) si (7.2) se obtine ecuatia conului superior
Z=

3(1

X 2 + Y 2 ).

Ecuatia conului inferior se obtine analog


Z=


3( X 2 + Y 2 1).

Prin urmare
Z=

!
p
2 + y2
x
3 sgn(x2 + y 2 1) 1 2 2
.
x + y2 + 1

Fie N 0 punctul de coordonate


2x
XN 0 = XN = x2 +y
2 +1
2y
YN 0 = YN = x2 +y2 +1



2 +y 2
x
ZN 0 =
3 sgn(x2 + y 2 1) 1 2 x2 +y2 +1

Efectuam cele trei operatii descrise anterior care duc corpul format de cele doua conuri
(7.8) n cubul culorilor [0, 1]3 .

113

7.4. VIZUALIZAREA FUNCT


IILOR COMPLEXE

1. Transformarea de omotetie a punctului N are ca rezultat punctul N1 de coordonate


XN1 =
YN1 =
ZN1

x
x2 +y 2 +1
y
x2 +y 2 +1

=
3 sgn(x2 + y 2 1)

1
2

x2 +y 2
x2 +y 2 +1

~ J,
~ K
~ versorii axelor de coordonate n sistemul XY Z si cu
2. Rotatia. Notand prin I,
~, ~, ~k versorii axelor n spatiul cubului culorilor rgb, avem (Fig. 7.9)
~ = 1 (~ + ~ + ~k).
Z
3

b
6

~
~k 6 Z

~

g
-

Fig. 7.9: Versori n cubul culorilor.


~ deci admit reprezentari de forma
Versorii I~ si J~ sunt perpendiculari pe K,
I~ = a~ + b~ (a + b)~k, a, b R, a 0,
J~ = c~ + d~ (c + d)~k, c, d R, c 0.
~ = 1 implica a2 + ab + b2 =
Conditia |I|
Analog, rezulta d =
Prin urmare

c 23c2
.
2

1
2

de unde b =

a 23a2
.
2

2
2
~k,
I~ = a~ + a223a ~ a 23a
2
2
2
c
23c
c
23c
~k.
J~ = c~ +
~
2
2

~ J~ I~ J~ = 0 implica
Conditia de ortogonalitate I

a 2 3a2 c 2 3c2 a 2 3a2 c 2 3c2


ac +

= 0. (7.3)
2
2
2
2

114

CAPITOLUL 7. GENERAREA REPREZENTARILOR


GRAFICE

Daca pentru alegem simultan acelasi semn atunci relatia anterioara devine 3ac +
p
(2 3a2 )(2 3c2 ) = 0, relatie care nu poate avea loc.
Prin urmare semnele n I~ si J~ trebuie sa fie contrare, de unde

2
2
~k,
I~ = a~ + a+223a ~ a+ 23a
2
2
2
c
c
23c
23c
~k.
J~ = c~ +
~
2
2

p
Conditia de ortogonalitate (7.3) devine 3ac (2 3a2 )(2 3c2 ) = 0, de unde se
obtine
r
2 3a2
.
c=
3
Valoarea lui a se determina astfel ncat axa OX sa fie cat mai apropiata de axa Or
din spatiul culorilor. In acest fel, valorile reale se vor reprezenta n rosu.
Exprimam conditia de apropiere prin cerinta ca expresia
|I~ ~|

(7.4)

sa fie minima.
Prin calcul direct |I~ ~|2 = 2 2a. Conditiile 2 3a2 0, a 0 implica a [0, 26 ].
Minimul expresiei (7.4) se obtine pentru a = 2 . In consecinta
6

I~ = 26~ 16 ~
J~ = 12~ 12 ~,
sau

2 ~
k,
6


~ 2
16 16
I
6
1
J~ =
12

0
2
1
1
1
~

K
3

~
~ .
~k

In urma rotatiei punctul N1 se transforma ntr-un punct N2 ale carui coordonate


sunt

1
0
xN2
xN 1
6
3
1
1
1
yN2 =
6 2 3 yN1 .
zN2
zN1
16 12 13
3. In urma translatiei din spatiul cubului culorilor, formulele de calcul ale componentelor culorii devin

x2 +y 2
1
1
2
x
1
2
2

r = 2 + xN2 = 2 + 6 x2 +y2 +1 + sgn(x + y 1)( 2 x2 +y2 +1 )

x2 +y 2
y
1
1
1
1
1
x
2
2
(7.5)
g = 2 + yN2 = 2 6 x2 +y2 +1 + 2 x2 +y2 +1 + sgn(x + y 1)( 2 x2 +y2 +1 )

2
2
x +y
b = 21 + zN2 = 12 16 x2 +yx2 +1 12 x2 +yy 2 +1 + sgn(x2 + y2 1)( 12 x2 +y2 +1 )

7.4. VIZUALIZAREA FUNCT


IILOR COMPLEXE

115

Aplicatia de vizualizare
Formulele (7.5) le vom folosi ntr-o aplicatie de vizualizarea unei functii complexe.
Pentru orice functie f , se vor afisa doua panouri, unul corespunzand vizualizarii functiei
z 7 z, cu rol de calibrare a perceptiei vizuale, iar celalalt panou destinat vizualizarii
functiei f, z D. Cele doua reprezentari sunt programate n metodele refPlot si fctPlot
ale clasei ComplexPlot.
In plus, daca xm = 2, xM = 2, ym = 2, yM = 2 atunci sunt reprezentate dreptele
=z = 0, <z = 0, arg(z) = 4 si cercurile |z| = 12 , |z| = 1, |z| = 32 , respectiv imaginile lor
prin f.
Clasele Java ale aplicatiei au codurile
1
2
3
4
5
7
8
9
10
12
13
14
15
16
18
19
20
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

package c o m p l e x p l o t ;
import j a v a . awt . image . B u f f e r e d I m a g e ;
import j a v a . awt . G r a p h i c s ;
import j a v a . awt . C o l o r ;
import o r g . nfunk . j e p . t y p e . Complex ;
public c l a s s ComplexPlot {
DataIn d i n=n u l l ;
int P;
i n t Q;
ComplexPlot ( DataIn d i n ) {
t h i s . d i n=d i n ;
P=d i n . getXDim ( ) ;
Q=d i n . getYDim ( ) ;
}
double sgn ( double x ) {
return x>0 ? 1 : ( x<0 ? 1 : 0 ) ;
}
BufferedImage r e f P l o t (){
double xm=d i n . getXm ( ) ;
double ym=d i n . getYm ( ) ;
double xM=d i n . getXM ( ) ;
double yM=d i n . getYM ( ) ;
double mx=(xMxm) /P ;
double my=(yMym) /Q;
B u f f e r e d I m a g e b i=new B u f f e r e d I m a g e (P , Q, B u f f e r e d I m a g e . TYPE 3BYTE BGR ) ;
G r a p h i c s gh=b i . g e t G r a p h i c s ( ) ;
Complex w ;
double u , v , s , R, R2 , xx , yy ;
float b , g , r ;
f o r ( i n t p=0;p<P ; p++){
f o r ( i n t q =0;q<Q; q++){
u=xm+mxp ;
v=yMmyq ;
R=Math . s q r t ( uu+vv ) ;
R2=RR+1;
s=sgn (R1)(0.5 R/R2 ) ;
xx=u/R2/Math . s q r t ( 6 ) ;
yy=v/R2/Math . s q r t ( 2 ) ;
r =( f l o a t ) ( 0 . 5 + s +2xx ) ;
g=( f l o a t ) ( 0 . 5 + sxx+yy ) ;
b=( f l o a t ) ( 0 . 5 + sxxyy ) ;
gh . s e t C o l o r (new C o l o r ( r , g , b ) ) ;
gh . f i l l R e c t ( p , q , 1 , 1 ) ;
}
}
gh . s e t C o l o r ( C o l o r .BLACK) ;
gh . drawLine ( 0 ,Q/ 2 ,P ,Q/ 2 ) ;

116

CAPITOLUL 7. GENERAREA REPREZENTARILOR


GRAFICE

gh . drawLine (P/ 2 , 0 ,P/ 2 ,Q) ;


gh . drawLine ( 0 , 0 , P ,Q) ;
gh . drawLine ( 0 ,Q, P , 0 ) ;
gh . s e t C o l o r ( C o l o r .GREEN) ;
gh . drawOval (P/ 4 ,Q/ 4 ,P/ 2 ,Q/ 2 ) ;
gh . drawOval ( 3 P/ 8 , 3 Q/ 8 ,P/ 4 ,Q/ 4 ) ;
gh . drawOval (P/ 8 ,Q/ 8 , 3 P/ 4 , 3 Q/ 4 ) ;
return b i ;

52
53
54
55
56
57
58
59
60

62

BufferedImage f c t P l o t (){
double xm=d i n . getXm ( ) ;
double ym=d i n . getYm ( ) ;
double xM=d i n . getXM ( ) ;
double yM=d i n . getYM ( ) ;
double mx=(xMxm) /P ;
double my=(yMym) /Q;
B u f f e r e d I m a g e b i=new B u f f e r e d I m a g e (P , Q, B u f f e r e d I m a g e . TYPE 3BYTE BGR ) ;
G r a p h i c s gh=b i . g e t G r a p h i c s ( ) ;
Complex w ;
double x=0 ,y=0 ,u , v , s , R, R2 , xx , yy ;
float b , g , r ;
f o r ( i n t p=0;p<P ; p++){
f o r ( i n t q =0;q<Q; q++){
x=xm+mxp ;
y=yMmyq ;
w=d i n . f c t ( x , y ) ;
u=w . r e ( ) ;
v=w . im ( ) ;
R=Math . s q r t ( uu+vv ) ;
R2=RR+1;
s=sgn (R1)(0.5 R/R2 ) ;
xx=u/R2/Math . s q r t ( 6 ) ;
yy=v/R2/Math . s q r t ( 2 ) ;
r =( f l o a t ) ( 0 . 5 + s +2xx ) ;
g=( f l o a t ) ( 0 . 5 + sxx+yy ) ;
b=( f l o a t ) ( 0 . 5 + sxxyy ) ;
gh . s e t C o l o r (new C o l o r ( r , g , b ) ) ;
gh . f i l l R e c t ( p , q , 1 , 1 ) ;
}
}
i n t vx , vy ;
i n t [ ] d={P , P , ( i n t ) ( PMath . s q r t ( 2 ) ) , ( i n t ) ( PMath . s q r t ( 2 ) ) , 1 0 0 0 , 1 0 0 0 , 1 0 0 0 } ;
f o r ( i n t k =0;k<d . l e n g t h ; k++){
f o r ( i n t p=0;p<d [ k ] ; p++){
switch ( k ) {
case 0 : x=xm+mxp ;
y=yMmyQ/ 2 ;
break ;
case 1 : x=xm+mxP/ 2 ;
y=yMmyp ;
break ;
case 2 : x=xm+mxp ;
y=yMmy (Pp ) ;
break ;
case 3 : x=xm+mxp ;
y=yMmyp ;
break ;
case 4 : u=P/2+P/4Math . c o s ( 2 Math . PI p/d [ 4 ] ) ;
v=Q/2+P/4Math . s i n ( 2 Math . PI p/d [ 4 ] ) ;
x=xm+mxu ;
y=yMmyv ;
break ;
case 5 : u=P/2+P/8Math . c o s ( 2 Math . PI p/d [ 4 ] ) ;
v=Q/2+P/8Math . s i n ( 2 Math . PI p/d [ 4 ] ) ;
x=xm+mxu ;
y=yMmyv ;

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

7.4. VIZUALIZAREA FUNCT


IILOR COMPLEXE

break ;
case 6 : u=P/2+3P/8Math . c o s ( 2 Math . PI p/d [ 4 ] ) ;
v=Q/2+3P/8Math . s i n ( 2 Math . PI p/d [ 4 ] ) ;
x=xm+mxu ;
y=yMmyv ;
break ;

119
120
121
122
123
124

}
i f ( k<4)
gh . s e t C o l o r ( C o l o r .BLACK) ;
else
gh . s e t C o l o r ( C o l o r .GREEN) ;
w=d i n . f c t ( x , y ) ;
i f ( ! w . isNaN ( ) ) {
u=w . r e ( ) ;
v=w . im ( ) ;
vx=( i n t ) ( ( uxm) /mx ) ;
vy=( i n t ) ( ( yMv ) /my ) ;
i f ((0<=vx)&&(vx<=P)&&(0<=vy)&&(vy<=Q) ) {
gh . f i l l R e c t ( vx , vy , 1 , 1 ) ;
}
}

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139

}
}
return b i ;

140
141
142

143
144

117

Datele problemei, adica functia complexa f, domeniul D si parametrii ferestrei P, Q sunt


retinute n clasa DataIn
1
2
3
5
6
7
8
9
10

package c o m p l e x p l o t ;
import o r g . nfunk . j e p . t y p e . Complex ;
import o r g . nfunk . j e p . ;
public c l a s s DataIn {
private double xm, ym, xM,yM;
private S t r i n g v a r ;
private S t r i n g e x p r ;
private i n t P=500;
private i n t Q=500;

12

JEP p a r s e r=n u l l ;

14

public void setXm ( double


t h i s . xm=xm ;
}
public void setYm ( double
t h i s . ym=ym ;
}
public void setXM ( double
t h i s .xM=xM;
}
public void setYM ( double
t h i s .yM=yM;
}

15
16
17
18
19
20
21
22
23
24
25
27
28
29
30
31
32
33
34
35
36
37

public double
return xm ;
}
public double
return ym ;
}
public double
return xM;
}
public double
return yM;

getXm ( ) {

getYm ( ) {

getXM ( ) {

getYM ( ) {

xm) {

ym) {

xM) {

yM) {

118

38

40

public S t r i n g getVar ( ) {
return v a r ;
}
public S t r i n g getExpr ( ) {
return e x p r ;
}

41
42
43
44
45

public void s e t P ( i n t P) {
t h i s . P=P ;
}
public i n t getP ( ) {
return P ;
}
public void setQ ( i n t Q) {
t h i s .Q=Q;
}
public i n t getQ ( ) {
return Q;
}

47
48
49
50
51
52
53
54
55
56
57
58

DataIn ( S t r i n g var , S t r i n g e x p r ) {
t h i s . v a r=v a r ;
t h i s . e x p r=e x p r ;
p a r s e r=new JEP ( ) ;
p a r s e r . addStandardFunctions ( ) ;
p a r s e r . addStandardConstants ( ) ;
p a r s e r . addComplex ( ) ;
p a r s e r . a d d V a r i a b l e ( var , 0 , 0 ) ;
p a r s e r . p ar s eE xp re ss i on ( expr ) ;
}

60
61
62
63
64
65
66
67
68
69

public Complex f c t ( double x , double y ) {


p a r s e r . a d d V a r i a b l e ( var , x , y ) ;
return p a r s e r . getComplexValue ( ) ;
}

71
72
73
74
75

CAPITOLUL 7. GENERAREA REPREZENTARILOR


GRAFICE

Panourile sunt afisate de cate o instanta a clasei PlotPanel

package c o m p l e x p l o t ;
import j a v a . awt . ;
import j a v a . t e x t . DecimalFormat ;

public c l a s s P l o t P a n e l extends j a v a x . swing . JPanel {

1
2

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

public P l o t P a n e l ( DataIn din , Image image , S t r i n g name ) {


i n t P=d i n . getP ( ) ;
i n t Q=d i n . getQ ( ) ;
initComponents ( ) ;
jLabelName . s e t T e x t ( name ) ;
DecimalFormat f=new DecimalFormat ( #0.0 ) ;
S t r i n g t x t=f . f o r m a t ( d i n . getXm ( ) ) ;
jLabelXm . s e t T e x t ( t x t ) ;
t x t=f . f o r m a t ( d i n . getXM ( ) ) ;
jLabelXM . s e t T e x t ( t x t ) ;
t x t=f . f o r m a t ( d i n . getYm ( ) ) ;
jLabelYm . s e t T e x t ( t x t ) ;
t x t=f . f o r m a t ( d i n . getYM ( ) ) ;
jLabelYM . s e t T e x t ( t x t ) ;
MyCanvas mc=new MyCanvas ( image ) ;
j P a n e l C a n v a s . s e t P r e f e r r e d S i z e (new Dimension ( d i n . getP ( ) , d i n . getQ ( ) ) ) ;
j P a n e l C a n v a s . s e t L a y o u t (new BorderLayout ( ) ) ;
j P a n e l C a n v a s . add (mc , BorderLayout .CENTER) ;
}

7.4. VIZUALIZAREA FUNCT


IILOR COMPLEXE

private void i n i t C o m p o n e n t s ( ) {
// cod g e n e r a t de Netbeans
}

27
28
29

private
private
private
private
private
private

31
32
33
34
35
36
37

j a v a x . swing . J L a b e l
j a v a x . swing . J L a b e l
j a v a x . swing . J L a b e l
j a v a x . swing . J L a b e l
j a v a x . swing . J L a b e l
j a v a x . swing . JPanel

jLabelName ;
jLabelXM ;
jLabelXm ;
jLabelYM ;
jLabelYm ;
jPanelCanvas ;

Clasa MyCanvas este cea utilizata n sectiunea 7.1.


Aplicatia este gestionata de clasa Main
1
2
3
4
6
7
8

11
12
13
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
48
49
50
51
52

package c o m p l e x p l o t ;
import j a v a . awt . image . B u f f e r e d I m a g e ;
import j a v a . awt . ;
public c l a s s Main extends j a v a x . swing . JFrame {
public Main ( ) {
initComponents ( ) ;
}

private void i n i t C o m p o n e n t s ( ) {
// cod g e n e r a t de Netbeans
}
private void jButtonComputeMouseClicked ( j a v a . awt . e v e n t . MouseEvent e v t )
S t r i n g v a r=j T e x t F i e l d V a r . g e t T e x t ( ) ;
S t r i n g e x p r=j T e x t F i e l d E x p r . g e t T e x t ( ) ;
DataIn d i n=new DataIn ( var , e x p r ) ;
i n t P=400;
i n t Q=400;
double v a l =(new Double ( jTextFieldXm . g e t T e x t ( ) ) ) . d o u b l e V a l u e ( ) ;
d i n . setXm ( v a l ) ;
v a l =(new Double ( jTextFieldYm . g e t T e x t ( ) ) ) . d o u b l e V a l u e ( ) ;
d i n . setYm ( v a l ) ;
v a l =(new Double ( jTextFieldXM . g e t T e x t ( ) ) ) . d o u b l e V a l u e ( ) ;
d i n . setXM ( v a l ) ;
v a l =(new Double ( jTextFieldYM . g e t T e x t ( ) ) ) . d o u b l e V a l u e ( ) ;
d i n . setYM ( v a l ) ;
d i n . s e t P (P ) ;
d i n . setQ (Q) ;
ComplexPlot cp=new ComplexPlot ( d i n ) ;
B u f f e r e d I m a g e b f 0=cp . r e f P l o t ( ) ;
P l o t P a n e l p0=new P l o t P a n e l ( din , ( Image ) bf0 , d i n . getVar ()+ > +
d i n . getVar ( ) ) ;
B u f f e r e d I m a g e b f=cp . f c t P l o t ( ) ;
P l o t P a n e l p f=new P l o t P a n e l ( din , ( Image ) bf , d i n . getVar ()+ > +
d i n . getExpr ( ) ) ;
S t r i n g t i t l e = R e p r e z e n t a r e a f u n c t i e i c o m p l e z e ;
j a v a x . swing . JFrame j f r a m e = new j a v a x . swing . JFrame ( t i t l e ) ;
jframe . addNotify ( ) ;
j f r a m e . getContentPane ( ) . s e t L a y o u t (new GridLayout ( 1 , 2 ) ) ;
j f r a m e . getContentPane ( ) . add ( p0 ) ;
j f r a m e . getContentPane ( ) . add ( p f ) ;
j f r a m e . s e t S i z e ( 2 P+120 ,Q+ 10 0) ;
j f r a m e . s e t V i s i b l e ( true ) ;
}
public s t a t i c void main ( S t r i n g a r g s [ ] ) {
j a v a . awt . EventQueue . i n v o k e L a t e r (new Runnable ( ) {
public void run ( ) {
new Main ( ) . s e t V i s i b l e ( true ) ;
}

119

120

CAPITOLUL 7. GENERAREA REPREZENTARILOR


GRAFICE

});

53
54

56

private
private
private
private
private
private
private
private
private
private
private
private
private

57
58
59
60
61
62
63
64
65
66
67
68
69

j a v a x . swing . JButton jButtonCompute ;


j a v a x . swing . J L a b e l j L a b e l E x p r ;
j a v a x . swing . J L a b e l j L a b e l V a r ;
j a v a x . swing . J L a b e l jLabelXM ;
j a v a x . swing . J L a b e l jLabelXm ;
j a v a x . swing . J L a b e l jLabelYM ;
j a v a x . swing . J L a b e l jLabelYm ;
j a v a x . swing . J T e x t F i e l d j T e x t F i e l d E x p r ;
j a v a x . swing . J T e x t F i e l d j T e x t F i e l d V a r ;
j a v a x . swing . J T e x t F i e l d jTextFieldXM ;
j a v a x . swing . J T e x t F i e l d jTextFieldXm ;
j a v a x . swing . J T e x t F i e l d jTextFieldYM ;
j a v a x . swing . J T e x t F i e l d jTextFieldYm ;

Cu aceasta aplicatie se obtin urmatoarele rezultate:

7.4. VIZUALIZAREA FUNCT


IILOR COMPLEXE

Fig. 7.10: Vizualizarea functiei f (z) = z 2 .

121

122

CAPITOLUL 7. GENERAREA REPREZENTARILOR


GRAFICE

Fig. 7.11: Vizualizarea functiei f (z) = z1 .

Fig. 7.12: Vizualizarea functiei f (z) =

z 2 1
.
z 2 +1

7.4. VIZUALIZAREA FUNCT


IILOR COMPLEXE

Fig. 7.13: Vizualizarea functiei f (z) = sin z.

Fig. 7.14: Vizualizarea functiei f (z) = exp z.

123

124

CAPITOLUL 7. GENERAREA REPREZENTARILOR


GRAFICE

Capitolul 8
Aplicatii Web
Retelele locale, internetul, raspandirea pe o arie geografica a resurselor si a locatiilor
n care se petrec actiuni ce tin de o activitate bine definita sau sunt urmarite, gestionate
din alte locuri au drept consecinta existenta aplicatiilor distribuite. Termenul distribuit
se refera tocmai la faptul ca componente ale aplicatiei se afla pe calculatoare diferite, dar
ntre care au loc schimburi de date. Daca partile unei aplicatii sau resursele utilizate se
gasesc pe calculatoare distincte atunci aplicatia se numeste distribuita.
Intre partile sau resursele unei aplicatii distribuite au loc schimburi de date la realizarea
carora concura sistemul de calcul, sistemul de operare si limbajul de programare.
Astfel, se vorbeste de programare distribuita ca mijloc de realizare a aplicatiilor distribuite.
Schimburile de date se pot realiza prin mai multe metode. Punem n evidenta doua
modele de aplicatii distribuite:
client-server: Programul server executa cererile clientilor.
Printre aplicatiile distribuite de tip client-server, n care comunicatiile se bazeaza
pe protocolul http, se disting
Aplicatii Web (site): cererea adresata serverului este lansata de o persoana
prin intermediul unui site, utilizand un program navigator (browser Web).
Servicii Web: cererea catre server se face de un program.
dispecer-lucr
ator: Programul dispecer distribuie sarcinile de executat lucratorilor
si le coordoneaza activitatea.
Limitandu-ne la aplicatii distribuite de tip client-server si la platforma Java, n acest
capitol se vor utiliza urmatoarele tehnologii de programare:
servlet-ul, care reprezinta tehnologia de baza pentru realizarea aplicatiilor Web n
Java;
websocket bazat pe protocolul omonim, introdus de HTML5.
Google Web Toolkit (GWT) cadru de lucru pentru dezvoltarea aplicatiilor Web.
125

126

CAPITOLUL 8. APLICAT
II WEB

Scopul urmarit este adaptarea programelor de calcul stiintific la aplicatii Web.


Componenta server a unei aplicatii Web
contine o clasa Java care se excuta de un server Web, compatibil;
este gestionata de serverul Web;
este capabila sa receptioneze si sa rapunda cererilor formulate de clienti.
Structura minimala a unei aplicatii Web este
catalogAplicatiei
|--> WEB-INF
|
|--> classes
|
|
|
*.class
|
|--> lib
|
|
|
*.jar
|
index.html
Catalogul classes contine fisierele class ale aplicatiei Web.
Catalogul lib este optional si va contine resursele jar suplimentare cerute de clasele
aplicatiei Web.
Prin intermediul fisierului index.html se apeleaza aplicatia Web. Acest fisier este
totodata si client Web. Adresa de apelare (URL - Universal Resource Locator ) a aplicatiei
Web este
http://host:port/catalogAplicatieiWeb
Daca n loc de index fisierul html de apelare are alt nume, de exemplu xyz.html atunci
adresa de apelare va fi
http://host:port/catalogAplicatieiWeb/xyz.html
host este numele calculatorului pe care ruleaza serverul Web - gazda aplicatiei Web. Portul
implicit utilizat de un server Web container de servlet este 8080.
Catalogul aplicatiei este denumit context-ul aplicatiei Web.
Programarea si utilizarea unei aplicatii Web necesita:
Cunoasterea elementului (marcaj, tag) html <form> pentru realizarea formularelor
de introducere a datelor;
Utilizarea unui server Web, container de servleti. Dintre produsele gratuite amintim:
apache-tomcat, jetty, glassfish.

8.1. SERVLET

8.1

127

Servlet

Interfata de programare (API) pentru servlet nu face parte din JDK, fiind implementat
de fiecare producator de server Web container de servlet.
Legatura dintre serverul Web cu clasa servlet-ului se poate realiza
programat prin adnotari1 n codul servlet-ului;
descriptiv n catalogul WEB-INF se editeaza fisierul web.xml.
In versiunile anterioare versiunii 3.0 ale interfetei de programare servlet aceasta a
fost unica optiune.
Trebuie demarcata diferenta dintre apelarea / lansarea n executie a clasei servlet de
apelarea aplicatiei Web.
Modul programat se bazeaza pe adnotarea javax.servlet.annotation.WebServlet
cu elementele:
String
name
String[ ]
urlPatterns
@InitParams[ ] initParam
boolean
asyncSupported
long
asyncTimeout
Modul descriptiv In fisierul web.xml apar elementele
1. <servlet> leaga numele servlet-ului definit n elementul <servlet-name> de
clasa servlet-ului dat n elementul <servlet-class> .
2. <servlet-mapping> defineste numele sub care servlet-ul identificat prin
<servlet-name> nume servlet< /servlet> se invoca din programul navigator.
Acest identificator - numeApel - se fixeaza n elementul <url-pattern> . Identificatorul are ca prefix caracterul / (slash).
Structura unui fisier web.xml este
1
2
3
4
5
6
7
8
9
10
11
12
13
14

<?xml version= 1 . 0 e n c o d i n g=UTF8 ?>


<webapp version= 3 . 0 xmlns= h t t p : // j a v a . sun . com/xml/ ns / j a v a e e
x m l n s : x s i= h t t p : //www. w3 . o r g /2001/XMLSchemai n s t a n c e >
< s e r v l e t>
<s e r v l e t name>n u m e s e r v l e t 1</ s e r v l e t name>
<s e r v l e t c l a s s>Nume clasa</ s e r v l e t c l a s s>
</ s e r v l e t>
< s e r v l e t>
<s e r v l e t name>n u m e s e r v l e t 2</ s e r v l e t name>
<s e r v l e t c l a s s>Nume clasa</ s e r v l e t c l a s s>
</ s e r v l e t>
. . .
<s e r v l e t mapping>
<s e r v l e t name>n u m e s e r v l e t 1</ s e r v l e t name>
1

In Java o adnotare (annotation) este o metadata a unui element de cod (identificator al unei entit
ati
din codul Java).
O adnotare poate s
a-si fac
a efectul asupra codului surss, naintea compilarii, asupra codului obiect,
dup
a compilare, dar naintea execut
arii sau n timpul executiei codului.

128

15
16
17
18
19
20
21
22

CAPITOLUL 8. APLICAT
II WEB

<u r l p a t t e r n>/ numeApel 1</ u r l p a t t e r n>


</ s e r v l e t mapping>
<s e r v l e t mapping>
<s e r v l e t name>n u m e s e r v l e t 2</ s e r v l e t name>
<u r l p a t t e r n>/ numeApel 2</ u r l p a t t e r n>
</ s e r v l e t mapping>
. . .
</webapp>

Unui element <servlet> i pot corespunde mai multe elemente <servlet-mapping>,


prin utilizarea de numeApel diferite.
Optional web.xml poate contine elementul
<welcome-file-list>
<welcome-file>
fisier.html sau jsp
</welcome-file>
</welcome-file-list>

cu precizarea fisierelor html sau jsp care apeleaza aplicatia Web. Declaratia fisierului
index.html este implicita.
Compilarea clasei servlet necesita completarea variabilei de mediu classpath cu
fisierul TOMCAT HOME\lib\servlet-api.jar.
Odata completata structura de cataloage si fisiere ale aplicatiei servlet aceasta structura trebuie copiata n catalogul TOMCAT HOME\webapps. Aceasta operatie se numeste
desf
asurarea (deployment) sau instalarea servlet-ului. Copierea se poate executa si cu
serverul Web pornit.
Pentru instalarea unui servlet exista mai multe alternative:
Din catalogul catalogAppServlet se realizeaza arhiva catalogAppServlet.war
jar cfv catAppServlet.war WEB-INF\ index.html
care se copiaza n catalogul TOMCAT HOME\webapps.
Serverul Web tomcat va dezarhiveaza arhiva. Astfel servlet-ul este instalat.
Aceasta instalare se numeste instalare dinamica - hot deployment.
Daca fisierul war este creat, atunci n locul copierii, instalarea se poate face prin
componenta manager a lui tomcat.
O alta posibilitate de instalare a unui servlet n serverul web tomcat este prin intermediul produsului apache-tomcat-deployer. apache-tomcat-deployer permite instalarea unui servlet de la distanta cat si instalarea comandata dintr-un program.

8.1.1

Codul unui servlet

Un servlet implementeaza interfata Servlet sau extinde una din clasele GenericServlet
sau HttpServlet. GenericServlet implementeaza interfata Servlet, iar HttpServlet
extinde clasa GenericServlet. Extinzand clasa GenericServlet nu este nevoie de rescrierea tuturor metodelor abstracte ale intrefetei Servlet.

8.1. SERVLET

129

Uzual clasa unui servlet va fi o clasa care extinde clasa HttpServlet, programatorul
va suprascrie metodele doGet(...) sau doPost(...), n functie de metoda utilizata de
client la lansarea cererii.
Practic, un servlet consta din scrierea metodelor
void init(ServletConfig config)
Aceasta metoda este optionala.
public void init(ServletConfig config) throws ServletException{
super.init(config);
// cod de initializare
}
Obiectul config are o metoda String getInitParameter(String numeParam) cu
ajutorul careia se pot recupera parametri de initializare asociati servlet-ului si care
se dau fie prin adnotarea @initParams, fie n fisierul web.xml prin elementele
<init-param>
<param-name> NumeleParametrului </param-name>
<param-value> Valoare </param-value>
</init-param>
cuprinse n elementul <servlet>.
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws
IOException, ServletException
Trateaza o cerere trimisa cu metoda GET (vezi marcajul <form>).
protected void doPost(HttpServletRequest req, HttpServletResponse res) throws
IOException, ServletException
Trateaza o cerere trimisa cu metoda POST (vezi marcajul <form>).
Activitatile de ntreprins ntr-o metoda doGet() sau doPost() sunt
1. Stabilirea naturii raspunsului:
res.setContentType(String tip)
unde tip specifica tipul MIME - Multipurpose Internet Mail Extensions al raspunsului:
"text/html" - pagina html;
"text/xml" - document xml;
"text/plain" - text;
"image/jpg" - imagine gif;
"image/gif" - imagine jpg.

130

CAPITOLUL 8. APLICAT
II WEB

2. Se obtine o referinta catre un obiect care realizeaza transmisia datelor catre navigatorul clientului:
ServletOutputStream out = res.getOutputStream();
sau
PrintWriter out=res.getWriter();
3. Se preiau datele cererii cu una din metodele:
String getParameter(String numeParapetru)
java.util.Enumeration getParameterNames()
4. Rezolva cererea clientului;
5. Formeaza si scrie raspunsul;
6. Inchide conexiunea obiectului prin care s-a realizat transmisia datelor catre navigatorul clientului prin out.close().
Un utilizator lanseaza o cerere catre servlet. De obicei acest lucru se realizeaza prin
clientul Web. Programul navigator trimite cererea serverului Web prin intermediul caruia
este lansat clasa servlet-ului n actiune.
Versiunea 3.0 a interfetei de programare pentru servlet ofera posibilitatea programarii
asincrone a actiunii servletului prin includerea acestuia ntr-un fir de executie.
Mai mult n versiunea 3.1, actiunea firului de executie este nlocuita prin programarea
unor interfete de tip listener.
Ciclul de viat
a al unui servlet. Cand un servlet este apelat prima data de catre
serverul Web se executa metoda init. Dupa aceasta, fiecarei cereri lansate de un utilizator
i se asociaza un fir de executie n care se apeleaza metoda service. Metoda service
apeleaza apoi metodele doGet(), doPost().
Exemplul 8.1.1 Servlet pentru calculul unei integrale.
Transformam aplicatia dezvoltata n (1.2) ntr-un servlet.
Codul servlet-ului va fi

10

package i n t e g r a l a ;
import j a v a . i o . IOException ;
import j a v a . i o . P r i n t W r i t e r ;
import j a v a x . s e r v l e t . S e r v l e t E x c e p t i o n ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e q u e s t ;
import j a v a x . s e r v l e t . h t t p . H t t p S e r v l e t R e s p o n s e ;
import j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
import m a t h l i b . c l i e n t . c v a d r a . ;
import m a t h l i b . c l i e n t . c v a d r a . impl . ;

12

@WebServlet ( u r l P a t t e r n s = / i n t e g )

14

public c l a s s M e t o d a S i m p s o n S e r v l e t extends H t t p S e r v l e t {

1
2
3
4
5
6
7
8
9

16
17
18
19

public void doGet ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )


throws S e r v l e t E x c e p t i o n , IOException {
S t r i n g a=r e q . g e t P a r a m e t e r ( a ) ;
S t r i n g b=r e q . g e t P a r a m e t e r ( b ) ;

8.1. SERVLET

S t r i n g v a r=r e q . g e t P a r a m e t e r ( s v a r ) ;
S t r i n g e x p r=r e q . g e t P a r a m e t e r ( e x p r ) ;
S t r i n g e p s=r e q . g e t P a r a m e t e r ( e p s ) ;
S t r i n g nmi=r e q . g e t P a r a m e t e r ( nmi ) ;
S t r i n g t i p=r e q . g e t P a r a m e t e r ( t i p ) ;
System . out . p r i n t l n ( v a r+ +e x p r+ +a+ +b+ +e p s+ +nmi+ +t i p ) ;
JepDataIn d i n=new JepDataIn ( var , e x p r ) ;
d i n . setA ( a ) ;
d i n . setB ( b ) ;
d i n . s e t E p s ( Double . p a r s e D o u b l e ( e p s ) ) ;
d i n . setNmi ( I n t e g e r . p a r s e I n t ( nmi ) ) ;
IMetodaSimpson o b j=new MetodaSimpsonWeb ( ) ;
DataOut dout=o b j . metodaSimpson ( d i n ) ;
r e s . setContentType ( t i p ) ;
P r i n t W r i t e r out=r e s . g e t W r i t e r ( ) ;
i f ( t i p . e q u a l s ( t e x t / html ) ) {
out . p r i n t l n ( <html> ) ;
out . p r i n t l n ( <head><t i t l e > </ t i t l e ></head> ) ;
out . p r i n t l n ( <body b g c o l o r=\#bbccbb\> ) ;
out . p r i n t l n ( <c e n t e r > ) ;
out . p r i n t l n ( <h1>C a l c u l u l i n t e g r a l e i p r i n metoda Simpson </h1> ) ;
out . p r i n t l n ( <p> ) ;
out . p r i n t l n ( I n d i c a t o r u l de r a s p u n s : + dout . g e t I n d ( ) ) ;
out . p r i n t l n ( </p> ) ;
out . p r i n t l n ( <p> ) ;
out . f o r m a t ( I n t e g r a l a : %1$12 . 6 f , dout . g e t I n t e g r a l a ( ) ) ;
out . p r i n t l n ( </p> ) ;
out . p r i n t l n ( <p> ) ;
out . p r i n t l n ( Numarul i t e r a t i i l o r e f e c t u a t e : + dout . g e t N i ( ) ) ;
out . p r i n t l n ( </p> ) ;
out . p r i n t l n ( <br/> ) ;
out . p r i n t l n ( </ c e n t e r > ) ;
out . p r i n t l n ( </body> ) ;
out . p r i n t l n ( </html> ) ;
}
else {
out . p r i n t l n ( I n d i c a t o r u l de r a s p u n s : +dout . g e t I n d ( ) ) ;
out . p r i n t l n ( I n t e g r a l a : +dout . g e t I n t e g r a l a ( ) ) ;
out . p r i n t l n ( Numarul i t e r a t i i l o r e f e c t u a t e : +dout . g e t N i ( ) ) ;
}
out . c l o s e ( ) ;

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

63

public void doPost ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )


throws S e r v l e t E x c e p t i o n , IOException {
doGet ( req , r e s ) ;
}

64
65
66
67

131

Pentru fixarea naturii raspunsului text/html sau text/plain s-a introdus variabila
tip, care n fisierul de invocare index.html primeste pe ascuns valoarea text/html. In
cazul n care vom apela servlet-ul dintr-un program, va fi mai avantajos sa primim
raspunsul ca text/plain.
Desfasurarea servlet-ului este
appinteg
|--> WEB-INF
|
|--> classes
|
|
|--> integrala
|
|
|
|
MetodaSimpsonServlet.class
|
|
|--> lib
|
|
|
|
mathlib.jar
|
|
|
|
jep-2.4.1.jar
|
index.html

132

CAPITOLUL 8. APLICAT
II WEB

Codul clientului Web, adica fisierului index.html, este:


1
2
3
4
5
6
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

< ! doctype html>


<body bgcolor=#bbccbb >
<center>
<h1> Pagina de a p e l a r e a s e r v l e t u l u i MetodaSimpson </h1>
<p> <h3> C a l c u l u l u n e i i n t e g r a l e </h3>
<p>I n t r o d u c e t i :
<form method= p o s t
action= / a p p i n t e g / i n t e g >
<table border= 2 >
<tr>
<td> V a r i a b i l a de i n t e g r a r e : </td>
<td> <input type= t e x t name= s v a r s i z e =30 r e q u i r e d> </td>
</ tr>
<tr>
<td> E x p r e s i a f u n c t i e i de i n t e g r a t : </td>
<td> <input type= t e x t name= e x p r s i z e =30 r e q u i r e d> </td>
</ tr>
<tr>
<td> L i m i t a i n f e r i o a r a a i n t e r v a l u l u i : </td>
<td> <input type= t e x t name= a s i z e =30 r e q u i r e d> </td>
</ tr>
<tr>
<td> L i m i t a s u p e r i o a r a a i n t e r v a l u l u i : </td>
<td> <input type= t e x t name=b s i z e =30 r e q u i r e d> </td>
</ tr>
<tr>
<td> T o l e r a n t a : </td>
<td> <input type= t e x t name= e p s value= 1 . 0 e8 s i z e =30 r e q u i r e d> </td>
</ tr>
<tr>
<td> Numar maxim admis de i t e r a t i i : </td>
<td> <input type= t e x t name=nmi value= 50 s i z e =30 r e q u i r e d> </td>
</ tr>
<tr>
<td a l i g n= c e n t e r > <input type= submit value= C a l c u l e a z a > </td>
<td> </td>
</ tr>
</ table>
<input type= h id de n name= t i p value= t e x t / html >
</form>
</ center>
</body>
</html>

Pe langa un client Web se pot realiza si programe client.

8.1.2

Program client al unui servlet

Apelarea unui servlet dintr-un program Java adica lansarea unei cereri si receptionarea
raspunsului furnizat de servlet se poate obtine cu produsul httpcomponents-client dezvoltat de apache.
Intr-un asemenea caz, din punctul de vedere al clientului este mai avantajos ca raspunsul
servlet-ului fie text/plain, n loc de text/html.
Exista mai multe modalitati de programare dintre care vom utiliza varianta de programare fluenta.
Exemplul 8.1.2 Program client pentru servlet-ul MetodaSimpson (8.1.1):

8.1. SERVLET

1
2
3
4
6
7

package i n t e g r a l a ;
import j a v a . u t i l . S c a n n e r ;
import o r g . apache . h t t p . c l i e n t . f l u e n t . Form ;
import o r g . apache . h t t p . c l i e n t . f l u e n t . Request ;
public c l a s s C l i e n t {
static S t r i n g u r l = http :// l o c a l h o s t :8080/ appinteg / i n t e g ;
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
System . out . p r i n t l n ( I n t r o d u c e t i : ) ;
System . out . p r i n t l n ( V a r i a b i l a ) ;
S t r i n g s v a r=s c a n n e r . n e x t ( ) ;
System . out . p r i n t l n ( E x p r e s i a de i n t e g r a t ) ;
S t r i n g e x p r=s c a n n e r . n e x t ( ) ;
System . out . p r i n t l n ( L i m i t a i n f e r i o a r a ) ;
double a=s c a n n e r . nextDouble ( ) ;
System . out . p r i n t l n ( L i m i t a s u p e r i o a r a ) ;
double b=s c a n n e r . nextDouble ( ) ;
System . out . p r i n t l n ( T o l e r a n t a ) ;
double e p s=s c a n n e r . nextDouble ( ) ;
System . out . p r i n t l n ( Numar maxim admis de i t e r a t i i ) ;
i n t nmi=s c a n n e r . n e x t I n t ( ) ;
try {
S t r i n g r e s u l t=Request . Post ( u r l )
. bodyForm ( Form . form ( )
. add ( s v a r , s v a r )
. add ( e x p r , e x p r )
. add ( a ,new Double ( a ) . t o S t r i n g ( ) )
. add ( b ,new Double ( b ) . t o S t r i n g ( ) )
. add ( e p s ,new Double ( e p s ) . t o S t r i n g ( ) )
. add ( nmi ,new I n t e g e r ( nmi ) . t o S t r i n g ( ) )
. add ( t i p , t e x t / p l a i n )
. build ())
. execute ( ) . returnContent ( ) . asString ( ) ;
System . out . p r i n t l n ( r e s u l t ) ;
}
catch ( E x c e p t i o n e ) {
e . printStackTrace ( ) ;
}
}

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

8.1.3

Dezvoltarea unui servlet prin maven

Dorim sa prezentam dezvoltarea aplicatiei servlet prin intermediul lui maven.


Dezvoltarea servlet-ului revine la parcurgerea pasilor:
1. Generarea aplicatiei:
set GroupID=integrala
set ArtifactID=appinteg
set Version=1.0
mvn -B archetype:generate
-DgroupId=%GroupID%
-DartifactId=%ArtifactID%
-Dversion=%Version%
-DarchetypeArtifactId=maven-archetype-webapp

2. Se adapteaza structura de cataloage si fisiere la

133

134

CAPITOLUL 8. APLICAT
II WEB

appinteg
|-- src
|
|-- main
|
|
|-- java
|
|
|
|-- integrala
|
|
|
|
|
MetodaSimpsonServlet.java
|
|
|-- resources
|
|
|-- webapp
|
|
|
|-- WEB-INF
|
|
|
|
|-- lib
|
|
|
|
|
|
mathlib.jar
|
|
|
|
|
|
jep-2.4.1.jar
|
|
|
|
|
web.xml
|
|
|
|
index.html
|
pom.xml

3. Fisierul pom.xml se completeaza cu


Referinta la javax.servlet.servlet-api necesara compilarii,
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
</dependency>

Referintele catre pachetele mathlib.client.cvadra, mathlib.client.cvadra.impl, jep


aflate n depozitul local maven
<dependency>
<groupId>mathlib.client.cvadra</groupId>
<artifactId>icvadra</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>mathlib.client.cvadra.impl</groupId>
<artifactId>cvadraimpl</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>jep</groupId>
<artifactId>jep</artifactId>
<version>2.4.1</version>
</dependency>

4. Deoarece s-a utilizat modul programat la programarea servletului - introdus de


servlet-api 3.0 - fisierul web.xml trebuie nlocuit cu
1
2
3
4

? xml v e r s i o n= 1 . 0 e n c o d i n g=UTF8?>
<webapp version= 3 . 0 xmlns= h t t p : // j a v a . sun . com/xml/ ns / j a v a e e
x m l n s : x s i= h t t p : //www. w3 . o r g /2001/XMLSchemai n s t a n c e >
</webapp>

5. Prelucrarea revine la mvn clean package


Arhiva war creata n catalogul target al proiectului se poate desfasura n orice
server Web.
Avem posibilitatea sa verificam aplicatia din maven:

8.1. SERVLET

135

1. Se completeaza fisierul pom.xml n elementul <build> cu


<plugins>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.3.6.v20151106</version>
</plugin>
</plugins>

Versiunea trecuta se poate actualiza.


2. Se modifica n fisierul index.html al aplicatiei servlet atributul action n integ si se
reia comanda mvn clean package.
3. Se lanseaza serverul Web jetty mvn jetty:run
4. Dintr-un navigator, aplicatia se apeleaza http://localhost:8080.

8.1.4

Servlet ca modul OSGi

Integrarea unei aplicatii Web ntr-o platforma OSGi necesita o abordare specifica.
Integrata ntr-o platforma OSGi, aplicatia Web nu mai este desfasurata nemijlocit n
serverul Web, dar apelurile se vor adresa n continuare serverului Web.
Integrarea unei aplicatii servlet ntr-o componenta OSGi se va baza pe interfata
org.osgi.service.http.HttpService, pentru care vom folosi implemantarea org.apache.felix.
http.bundle-*.jar. Cu foarte putine diferente, n varianta de programare pe care o
prezenta, componenta OSGi se va putea utiliza pe platformele OSGi apache-karaf si
glassfish.
Interfata HttpService declara metodele
void registerResources(String alias, String name, HttpContext context)
throws NamespaceException
void registerServlet(String alias, Servlet servlet, Dictionary initparams,
HttpContext context)ServletException, NamespaceException
void unregister(String alias)
Structura componentei OSGi corespunzatoare unui servlet este
|-->
|
|
|
|

META-INF
|
MANIFEST.MF
ClasaServlet.class
Activator.class
fisier.html

136

CAPITOLUL 8. APLICAT
II WEB

Ramane la latitudinea programatorului sa includa sau nu pagina html.


Clasa servlet-ului ramane nemodificata iar n clientul Web reprezentat de fisierul html
doar valoarea atributului action difera:
Cadrul OSGi
apache-karaf
glassfish

Apel (aplicatie, servlet)


http://host:8080/fisier.html
/numeApel
http://host:8080/osgi/fisier.html
/osgi/numeApel

Exemplul 8.1.3 Clasa activatorului pentru servletul MetodaSimpson 8.1.1.

import
import
import
import

public c l a s s A c t i v a t o r implements B u n d l e A c t i v a t o r {

1
2
3

osgi
osgi
osgi
osgi

. framework . B u n d l e A c t i v a t o r ;
. framework . BundleContext ;
. framework . S e r v i c e R e f e r e n c e ;
. s e r v i c e . http . HttpService ;

public void s t a r t ( BundleContext c o n t e x t ) throws E x c e p t i o n {


S e r v i c e R e f e r e n c e s R e f = c o n t e x t . g e t S e r v i c e R e f e r e n c e ( H t t p S e r v i c e . c l a s s . getName ( ) ) ;
i f ( s R e f != n u l l ) {
HttpService s e r v i c e = ( HttpService ) context . g e t S e r v i c e ( sRef ) ;
s e r v i c e . r e g i s t e r S e r v l e t ( / i n t e g ,new i n t e g r a l a . M e t o d a S i m p s o n S e r v l e t ( ) , null , n u l l ) ;
s e r v i c e . r e g i s t e r R e s o u r c e s ( / a p p i n t e g , / i n d e x . html , n u l l ) ;
}
}

8
9
10
11
12
13
14
15

public void s t o p ( BundleContext c o n t e x t ) throws E x c e p t i o n {}

17
18

org .
org .
org .
org .

In acest caz structura modulului OSGi este


|-->integrala
|
|
MetodaSimpsonServlet.class
|-->lib
|
|
mathlib.jar
|
|
jep-2.4.1..jar
|--> META-INF
|
|
MANIFEST.MF
|
Activator.class
|
index.html

unde manifest.mf este


1
2
3
4
5
6
7
8
9
10

M a n i f e s t V e r s i o n : 1 . 0
BundleM a n i f e s t V e r s i o n : 2
BundleName: M e t o d a S i m p s o n S e r v l e t
BundleSymbolicName: a p p i n t e g
BundleV e r s i o n : 1 . 0 . 0
BundleA c t i v a t o r : A c t i v a t o r
BundleL o c a l i z a t i o n : p l u g i n
ImportP a c k a g e : j a v a x . s e r v l e t , j a v a x . s e r v l e t . http , o r g . o s g i . framework ; v e r s i o n= 1 . 3 . 0 ,
o r g . o s g i . s e r v i c e . h t t p ; v e r s i o n= 1 . 2 . 0
BundleC l a s s p a t h : . , l i b / m a t h l i b . j a r , l i b / j e p 2 . 4 . 1 . j a r

137

8.1. SERVLET

Detalii de operare - apache-karaf


Lansarea produsului se poate prin fisierul de comenzi
set JAVA_HOME=. . .
set KARAF_HOME=. . .
del %KARAF_HOME%\lock
del %KARAF_HOME%\instances\*
rmdir %KARAF_HOME%\instances
%KARAF_HOME%\bin\karaf.bat clean

In catalogul %KARAF HOME% se genereaza catalogul instances iar n fereastra DOS va


apare prompt-ul karaf@root>.
Oprirea se obtine apasand tastele CTRL+D.
Karaf poseda o consola DOS dar si o consola Web.
Instalarea componentelor OSGi se poate face
copiindu-le n catalogul
%KARAF HOME%\deploy
n mod obisnuit, prin comanda install file:. . .
In acest caz fisierul MANIFEST.mf trebuie sa contina atributele
Bundle-ManifestVersion: 2
Bundle-SymbolicName: numeComponentaOSGi

Comenzi OSGi uzuale sunt: start n, stop n, install file:..., uninstall n, list,
help.
Mediul OSGi apache-karaf utilizeaza serverul Web incorporat Jetty pe portul 8181.
Pentru a schimba portul se creaza n prealabil fisierul etc\org.ops4j.pax.web.cfg cu
continutul
org.osgi.service.http.port=8080
Trebuie instalat suportul pentru protocolul http prin
feature:install http
Apelarea unei aplicatii servlet va fi http://host:port/fisier.html

Detalii de operare - glassfish


Mediul OSGi are la baza platforma apache-felix. Dupa lansarea serverului de aplicatii
glassfish comenzile OSGi se apeleaza prin
asadmin osgi comanda OSGi
Astfel pentru lansarea unui servlet se va executa comanda:
asadmin osgi start file:.../arhiva.jar
Apelarea aplicatiei servlet va fi http://host:port/osgi/fisier.html

138

CAPITOLUL 8. APLICAT
II WEB

8.2

WebSocket

Protocolul websocket se initiaza dintr-o comunicatie bazata pe protocolul http prin


mecanismul upgrade, introdus de servlet-api 3.0: Intr-un mesaj http trimis de client se
indica solicitarea de trecere de la protocolul http la protocolul WebSocketprin prezenta
antetului Upgrade: websocket. Exemplul unui asemenea mesaj este
GET /HelloWebSocket/hello HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: localhost:9090
Origin: null
Sec-WebSocket-Key: tLZ8VGZ8Cw8kt0BvhuV6Vw==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: x-webkit-deflate-frame
Cookie: JSESSIONID=2BCFF666164139524DD92D573C3859F7;
JSESSIONID=bf12d2417e8eb1bcd6da6137af9d;
treeForm_tree-hi=treeForm:tree:applications

Mesajul de raspuns afirmativ este


HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: ZDE5NmS4T9spIby8/vo/V+rbNAs=

Daca ntre cei doi parteneri se stabileste acordul (handshake) atunci restul comunicatiilor
au loc prin intermediul unui soclu TCP pe portul 80.
Astfel ciclul de viata al procesului de comunicatie este:
1. Un client solicita printr-un mesaj http acordul pentru trecerea la protocolul WebSocket.
2. Serverul raspunde acceptand acordul.
3. Odata stabilita conexiunea, acesta devine bidirectionala (simetrica), clientul si serverul
transmit si receptioneaza mesaje.
4. Una din parti nchide conexiunea.

8.2.1

Interfata de programare HTML5 de client WebSocket

Interfata de programare este definita de un obiect JavaScript:


Constructor
WebSocket(in String uri )
unde uri este de forma ws://host:port/context/numeApel
Functii
attribute function onopen(evt)
attribute function onmessage(evt)
attribute function onerror(evt)

139

8.2. WEBSOCKET

attribute function onclose(evt)


boolean send(in String data)
close()
Atribute
readyState
Starea conexiunii:
Valoare
0
1
2
3

Semnificatia
Nu s-a stabilit conexiunea
Conexiune pregatita pentru comunicatii
Conexiune n pragul confirmarii (handshake)
Conexiune nchisa si nu mai poate fi redeschisa

bufferedAmount
Numarul octetilor trimisi de functia send. Datele sunt codificate UTF-8.
Un sablon de utilizare poate fi
<script language="javascript" type="text/javascript">
var wsUri = "ws://host:8080/context/numeApel";
var websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) { . . . };
websocket.onmessage = function(evt) { . . . };
websocket.onerror = function(evt) { . . . };
websocket.onclose = function(evt) { . . . };
. . .
</script>

Expedierea datelor.
Consideram formularul HTML
<form name="myform">
<input type="text" name="xyz" . . ./>
. . .
<input type="button" onclick="send"/>
</form>

Sablonul functiei send este


function send(){
var xyz=document.myform.xyz.value;
websocket.send(xyz);
}

Receptia unui rezultat furnizat de server. Functia onmessage permite recuperarea rezultatului din evt.data.

140

CAPITOLUL 8. APLICAT
II WEB

8.2.2

WebSocket n Java

Interfata de programare Java pentru WebSocket declara clase atat pentru server cat
si pentru client.
Programarea serverului se poate realiza prin adnotari (Annotation driven) potrivit
ablonului
@ServerEndpoint(value="/urlPattern")
public class EndpointWebSocketServer {
private static Set<Session> sessions =
Collections.synchronizedSet(new HashSet<Session>());
@OnMessage
public void myTask(String msg, Session session)
throws IOException,EncodeException{
. . .
}
@OnOpen
public void onOpen(Session session){
sessions.add(session);
}
@OnClose
public void onClose(Session session){
sessions.remove(session);
}
}

Metoda cu adnotareae @OnMessage asigura accesul la datele cererii unui client.


Acest sablon necesita familiarizarea cu componente din interfata de programare WebSocket.
Interfata javax.websocket.Session
Metode
void addMessageHandler(MessageHandler handler )
RemoteEndpoint.Basic getBasicRemote()
Prin intermediul unui obiect de tip RemoteEndpoint.Basic se programeaza expedierea raspunsului catre client.
RemoteEndpoint.Async getAsyncRemote()
void close()
Interfata RemoteEndpoint are subinterfetele
RemoteEndpoint.Async
RemoteEndpoint.Basic.

8.2. WEBSOCKET

Interfata javax.websocket.RemoteEndpoint.Basic
Metode
void sendObject(Object data) throws IOException,EncodeException
void sendText(String data) throws IOException
void sendBinary(ByteBuffer data) throws IOException
OutputStream getSendStream() throws IOException
Exemplul 8.2.1 Aplicatie WebSocket pentru calculul unei integrale.
Aplicatia server are codul
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
20
21
22
23
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

package w e b s o c k e t . c v a d r a ;
import j a v a x . w e b s o c k e t . OnMessage ;
import j a v a x . w e b s o c k e t . s e r v e r . S e r v e r E n d p o i n t ;
import j a v a x . w e b s o c k e t . S e s s i o n ;
import j a v a x . w e b s o c k e t . OnOpen ;
import j a v a x . w e b s o c k e t . OnClose ;
import j a v a x . w e b s o c k e t . OnError ;
import j a v a x . w e b s o c k e t . RemoteEndpoint ;
import j a v a x . w e b s o c k e t . EncodeException ;
import j a v a . i o . IOException ;
import j a v a . u t i l . S e t ;
import j a v a . u t i l . C o l l e c t i o n s ;
import j a v a . u t i l . HashSet ;
import m a t h l i b . c l i e n t . c v a d r a . JepDataIn ;
import m a t h l i b . c l i e n t . c v a d r a . DataOut ;
import m a t h l i b . c l i e n t . c v a d r a . IMetodaSimpson ;
import m a t h l i b . c l i e n t . c v a d r a . impl . MetodaSimpsonWeb ;
import j a v a . t e x t . DecimalFormat ;
@ServerEndpoint ( v a l u e= / c v a d r a )
public c l a s s I n t e g r a l a W e b S o c k e t S e r v e r A d {
private s t a t i c Set<S e s s i o n > s e s s i o n s =
C o l l e c t i o n s . s y n c h r o n i z e d S e t (new HashSet<S e s s i o n > ( ) ) ;
@OnMessage
public void onMessage ( S t r i n g message , S e s s i o n s e s s i o n ) {
S t r i n g [ ] elem=message . s p l i t ( : ) ;
S t r i n g v a r=elem [ 0 ] ;
S t r i n g e x p r=elem [ 1 ] ;
JepDataIn d i n=new JepDataIn ( var , e x p r ) ;
d i n . setA ( elem [ 2 ] ) ;
d i n . setB ( elem [ 3 ] ) ;
d i n . s e t E p s ( Double . p a r s e D o u b l e ( elem [ 4 ] ) ) ;
d i n . setNmi ( I n t e g e r . p a r s e I n t ( elem [ 5 ] ) ) ;
S t r i n g t i p=elem [ 6 ] ;
IMetodaSimpson o b j=new MetodaSimpsonWeb ( ) ;
DataOut dout=o b j . metodaSimpson ( d i n ) ;
DecimalFormat d f=new DecimalFormat ( 0 . 0 0 0 0 0 0 1 ) ;
S t r i n g B u f f e r r e z=new S t r i n g B u f f e r ( ) ;
i f ( t i p . e q u a l s ( html ) ) {
r e z . append ( <t a b l e ><t r ><td> ) ;
r e z . append ( I n d i c a t o r u l de r a s p u n s : +dout . g e t I n d ( ) ) ;
r e z . append ( </td></t r ><t r ><td> ) ;
r e z . append ( I n t e g r a l a : +d f . f o r m a t ( dout . g e t I n t e g r a l a ( ) ) ) ;
r e z . append ( </td></t r ><t r ><td> ) ;
r e z . append ( Numarul i t e r a t i i l o r e f e c t u a l e : +dout . g e t N i ( ) ) ;
r e z . append ( </td></t r ></t a b l e > ) ;

141

142

CAPITOLUL 8. APLICAT
II WEB

}
else {
r e z . append ( I n d i c a t o r u l de r a s p u n s : +dout . g e t I n d ( ) ) ;
r e z . append ( \n ) ;
r e z . append ( I n t e g r a l a : +dout . g e t I n t e g r a l a ( ) ) ;
r e z . append ( \n ) ;
r e z . append ( Numarul i t e r a t i i l o r e f e c t u a l e : +dout . g e t N i ( ) ) ;
}
s e s s i o n s . stream ( )
. f i l t e r ( s>s . e q u a l s ( s e s s i o n ) )
. f o r E a c h ( s>{
RemoteEndpoint . B a s i c e n d p o i n t=s . getBasicRemote ( ) ;
try {
e n d p o i n t . sendText ( r e z . t o S t r i n g ( ) ) ;
}
catch ( IOException e ) { } ;
});

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

67

@OnOpen
public void onOpen ( S e s s i o n s e s s i o n )
throws IOException , EncodeException {
s e s s i o n s . add ( s e s s i o n ) ;
}

68
69
70
71

@OnClose
public void o n C l o s e ( S e s s i o n s e s s i o n ) {
s e s s i o n s . remove ( s e s s i o n ) ;
}

73
74
75
76
77

Clientul Web HTML5/Javascript este


1
2
3
4
5
7
8
9
10
11
12
13
15
16
17
19
20
21
22
23
24
25
26
27
28
29
31
32
33

< !DOCTYPE html>


<html>
<head>
<meta httpe q u i v= ContentType content= t e x t / html ; c h a r s e t=UTF8>
< t i t l e>IntegralaWebSocketAd</ t i t l e>
<s c r i p t l a n g u a g e= j a v a s c r i p t type= t e x t / j a v a s c r i p t >
v a r wsUri = ws : / / l o c a l h o s t : 8 0 8 0 / IntegralaWebSocketAd / c v a d r a ;
v a r w e b s o c k e t = new WebSocket ( wsUri ) ;
w e b s o c k e t . onopen = f u n c t i o n ( e v t ) { onOpen ( e v t ) } ;
w e b s o c k e t . onmessage = f u n c t i o n ( e v t ) { onMessage ( e v t ) } ;
websocket . o n e r r o r = f u n c t i o n ( evt ) { onError ( evt ) } ;
websocket . o n c l o s e = f u n c t i o n ( evt ) { onClose ( evt ) } ;
function i n i t () {
ou tp ut = document . getElementById ( r e s u l t ) ;
}
f u n c t i o n send ( ) {
v a r s v a r=document . c v a d r a . s v a r . v a l u e ;
v a r e x p r=document . c v a d r a . e x p r . v a l u e ;
v a r a=document . c v a d r a . a . v a l u e ;
v a r b=document . c v a d r a . b . v a l u e ;
v a r e p s=document . c v a d r a . e p s . v a l u e ;
v a r nmi=document . c v a d r a . nmi . v a l u e ;
v a r msg=s v a r+ : +e x p r+ : +a+ : +b+ : +e p s+ : +nmi+ : html ;
w e b s o c k e t . send ( msg ) ;
w r i t e T o S c r e e n ( SENT : + msg ) ;
}
f u n c t i o n onOpen ( e v t ) {
w r i t e T o S c r e e n ( CONNECTED ) ;
}

8.2. WEBSOCKET

35
36
37
39
40
41
43
44
45
47
48
49
51
52
53
54
55
56
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

f u n c t i o n onMessage ( e v t ) {
w r i t e T o S c r e e n ( RECEIVED : + e v t . data ) ;
}
f u n c t i o n onError ( evt ) {
w r i t e T o S c r e e n ( <span s t y l e= c o l o r : r e d ; >ERROR:</span> + e v t . data ) ;
}
f u n c t i o n onClose ( evt ) {
w r i t e T o S c r e e n ( CLOSED ) ;
}
f u n c t i o n myclose ( ) {
websocket . c l o s e ( ) ;
}
f u n c t i o n w r i t e T o S c r e e n ( message ) {
v a r p r e = document . c r e a t e E l e m e n t ( p ) ;
p r e . s t y l e . wordWrap = breakword ;
p r e . innerHTML = message ;
ou tp ut . appendChild ( p r e ) ;
}
window . a d d E v e n t L i s t e n e r ( l o a d , i n i t , f a l s e ) ;
</ s c r i p t>
</head>
<body bgcolor=#bbccbb >
<center>
<h1> Pagina de a p e l a r e a a p l i c a &#355; i e i w e b s o c k e t MetodaSimpson</h1>
<h3> C a l c u l u l u n e i i n t e g r a l e </h3>
<p/>I n t r o d u c e &#355; i :
< !<div s t y l e= t e x t a l i g n : c e n t e r ; >>
<form name= c v a d r a >
<table border= 2 >
<tr>
<td> V a r i a b i l a i n d e p e n d e n t a : </td>
<td> <input type= t e x t name= s v a r s i z e =30 r e q u i r e d> </td>
</ tr>
<tr>
<td> E x p r e s i a de i n t e g r a t : </td>
<td> <input type= t e x t name= e x p r s i z e =30 r e q u i r e d> </td>
</ tr>
<tr>
<td> L i m i t a i n f e r i o a r a a i n t e r v a l u l u i : </td>
<td> <input type= t e x t name= a s i z e =30 r e q u i r e d> </td>
</ tr>
<tr>
<td> L i m i t a s u p e r i o a r a a i n t e r v a l u l u i : </td>
<td> <input type= t e x t name=b s i z e =30 r e q u i r e d> </td>
</ tr>
<tr>
<td> T o l e r a n t a : </td>
<td> <input type= t e x t name= e p s value= 1 . 0 e8 s i z e =30 r e q u i r e d> </td>
</ tr>
<tr>
<td> Numar maxim admis de i t e r a t i i : </td>
<td> <input type= t e x t name=nmi value= 50 s i z e =30 r e q u i r e d> </td>
</ tr>
<tr>
<td>
<input type= b ut to n value= C a l c u l e a z a onclick= send ( ) />
</td>
<td></td>
</ tr>
<tr>
<td>
<input type= b ut to n value= I n c h i d e c o n e x i u n e a onclick= m y c l o s e ( ) />

143

144

102
103
104
105
106
107
108
109
110
111

CAPITOLUL 8. APLICAT
II WEB

</td>
<td></td>
</ tr>
</ table>
</form>
</ div>
<div id= r e s u l t ></ div>
</ center>
</body>
</html>

8.2.3

Client Java pentru WebSocket

Interfata de programare WebSocket permite realizarea de clase client. Programarea


clasei utilizeaza n plus:
Clasa javax.websocket.Endpoint
Metode
void onClose(Session session, CloseReason closeReason)
void onError(Session session, Throwable th)
abstract void onOpen(Session session, EndpointConfig config)
Clasa javax.websocket.ContainerProvider
Metode
public static WebSocketContainer getWebSocketContainer()
Interfata javax.websocket.WebSocketContainer
Metode
Session connectToServer(Endpoint endpointInstance,
ClientEndpointConfig cec, URI path) throws
DeploymentException,IOException
Exemplul 8.2.2 Program client pentru aplicatia WebSocket IntegralaWebSocketServerAd
(8.2.1).
1
2
3
4
5
6
7

import
import
import
import
import
import
import

j a v a . i o . IOException ;
j a v a . n e t . URI ;
javax . websocket . ContainerProvider ;
j a v a x . w e b s o c k e t . DeploymentException ;
j a v a x . w e b s o c k e t . WebSocketContainer ;
javax . websocket . S e s s i o n ;
java . u t i l . Scanner ;

11

import j a v a x . w e b s o c k e t . Endpoint ;
import j a v a x . w e b s o c k e t . E n d p o i n t C o n f i g ;
import j a v a x . w e b s o c k e t . MessageHandler ;

13

public c l a s s WebSocketClient extends Endpoint {

9
10

8.3. GOOGLE WEB TOOLKIT (GWT)

private s t a t i c boolean s f a r s i t =f a l s e ;
private s t a t i c S t r i n g s e r v e r = ws : / / l o c a l h o s t : 8 0 8 0 / IntegralaWebSocketAd / c v a d r a ;

14
15

public s t a t i c void main ( S t r i n g [ ] a r g s ) {


S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
System . out . p r i n t l n ( I n t r o d u c e t i : ) ;
System . out . p r i n t l n ( V a r i a b i l a i n d e p e n d e n t a ) ;
S t r i n g s v a r=s c a n n e r . n e x t ( ) ;
System . out . p r i n t l n ( E x p r e s i a de i n t e g r a t ) ;
S t r i n g e x p r=s c a n n e r . n e x t ( ) ;
System . out . p r i n t l n ( L i m i t a i n f e r i o a r a ) ;
S t r i n g a=s c a n n e r . n e x t ( ) ;
System . out . p r i n t l n ( L i m i t a s u p e r i o a r a ) ;
S t r i n g b=s c a n n e r . n e x t ( ) ;
System . out . p r i n t l n ( T o l e r a n t a ) ;
double e p s=s c a n n e r . nextDouble ( ) ;
System . out . p r i n t l n ( Numar maxim admis de i t e r a t i i ) ;
i n t nmi=s c a n n e r . n e x t I n t ( ) ;
S t r i n g msg=s v a r+ : +e x p r+ : +a+ : +b+ : +e p s+ : +nmi+ : t e x t ;
WebSocketContainer c o n t a i n e r = C o n t a i n e r P r o v i d e r . getWebSocketContainer ( ) ;
try {
S e s s i o n s e s s i o n=
c o n t a i n e r . c o n n e c t T o S e r v e r ( WebSocketClient . c l a s s , null , URI . c r e a t e ( s e r v e r ) ) ;
s e s s i o n . getBasicRemote ( ) . sendText ( msg ) ;
while ( ! s f a r s i t ) { System . out . p r i n t ( ) ; } ;
session . close ();
}
catch ( E x c e p t i o n ex ) {
System . out . p r i n t l n ( LocalEndPoint E x c e p t i o n : +ex . g e t M e s s a g e ( ) ) ;
}
}

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

public void onOpen ( S e s s i o n s e s s i o n , E n d p o i n t C o n f i g c o n f i g ) {


s e s s i o n . addMessageHandler (new MessageHandler . Whole<S t r i n g >() {
public void onMessage ( S t r i n g t e x t ) {
System . out . p r i n t l n ( R e z u l t a t e : ) ;
System . out . p r i n t l n ( t e x t ) ;
s f a r s i t =true ;
}
});
}

46
47
48
49
50
51
52
53
54
55

145

8.3

Google Web Toolkit (GWT)

GWT utilizeaza protocolul Asynchronous JavaScript And Xml (AJAX). La baza protocolului AJAX se afla o interfata de programare (API) care printr-un obiect XMLHttpRequest (XHR), poate fi utilizata de un limbaj de scripting, n particular Javascript, pentru
transfer de date catre un server Web prin protocolul HTTP;
manipularea datelor XML sau JSON (JavaScript Object Notation).
Caracterul asincron consta n faptul ca raspunsul furnizat de un program server reface
doar o parte din pagina html si nu ntrega pagina, asa cum este cazul utilizarii obisnuite
a unui servlet.
Din punct de vedere al structurii aplicatiei GWT, aceasta poate fi:

146

CAPITOLUL 8. APLICAT
II WEB

Simpla, fara apel de procedura la distanta. In acest caz, rezolvarea cererii este
programata n clase aflate n catalogul client.
Programatorul dezvolta aplicatia n Java si HTML iar GWT transforma partea de
client n JavaScript. Astfel se evita programarea n JavaScript.
Cu apel de procedura la distanta. Partea de server este bazata pe tehnologia servlet.
GWT este distribuit gratuit de firma Google.
Instalarea produsului consta din dezarhivarea fisierului descarcat din Internet.

8.3.1

Dezvoltarea unei aplicatii cu GWT

O aplicatie GWT o vom dezvolta cu apache-ant. Alternativ se poate utiliza apachemaven sau eclipse.
O aplicatie GWT se initiaza prin generarea unei structuri de cataloage si fisiere. Daca
se doreste realizarea unei aplicatii cu punctul de intrare dat de clasa context.MyApp si
care sa se afle ntr-un catalog catapp, atunci generarea se obtine prin comanda
webAppCreator -out catapp context.MyApp
lansata ntr-o fereasta DOS. Contextul poate reprezenta un sir de cataloage.
Rezultatul este reprezentat n Fig. 8.1 si corespunde unei aplicatii de ntampinare.
catapp
|-->
|
|
|
|
|
|
|
|
|
|
|-->
|
|-->
|
|
|
|
|
|
|
|
|
|

src
|--> context
|
|--> client
|
|
|
MyApp.java
|
|
|
GreetingService.java
|
|
|
GreetingServiceAsync.java
|
|--> server
|
|
|
GreetingServiceImpl.java
|
|--> shared
|
|
|
FieldVerifier.java
|
|
MyApp.gwt.xml
test
|
|
. . .
war
|--> WEB-INF
|
|
web.xml
|
MyApp.css
|
MyApp.html
|
favicon.ico
.classpath
.project
MyApp.launch
README.txt
build.xml

Fig. 8.1: Initializarea unei aplicatii GWT.


Acesta structura reprezinta un proiect GWT. Proiectul generat este punctul de plecare

147

8.3. GOOGLE WEB TOOLKIT (GWT)

pentru construirea oricarei alte aplicatii, a carei dezvoltare consta n modificarea, rescrierea fisierelor create si completarea cu altele noi. Pentru o aplicatie GWT se mai
foloseste si termenul de modul GWT.
Fisierul MyApp.gwt.xml este un fisier de configurare n care trebuie declarate modulele
externe utilizate.
O aplicatie GWT poate fi executata n
modul de dezvoltare. Rularea n acest mod se lanseaza prin ant devmode.
Verificarea aplicatiei se face prin intermediul navigatorului implicit.
modul Web, de productie - caz n care se genereaza arhiva war a aplicatiei. Se va
executa ant war.
Cu notatiile utilizate mai sus, va rezulta fisierul MyApp.war. Dupa desfasurarea
aplicatiei ntr-un server Web, container de servlet, se va apela http://host:port/My
App/MyApp.html.

Dezvoltarea unei aplicatii GWT simple


Dupa generarea proiectului, aplicatia GWT se dezvolta parcurgand pasii (se presupune
din nou ca numele aplicatiei este MyApp aflat n catalogul catapp):
1. Proiectarea interfetei grafice vizeaza elementele care se definesc n fisierul MyApp.html,
punctul de intrare n aplicatie. Un widget 2 (element, control) grafic va fi redat de
navigator ntr-o fanta (slot) definita, uzual, printr-un container div
<div id="slot" ></div>
2. Construirea interfetei grafice consta n definirea obiectelor Java care umplu fantele
declarate mai sus. Acest lucru se programeaza n clasa MyApp.java, care implementeaza interfata EntryPoint, interfata ce declara doar metoda
public void onModuleLoad().
Implementarea acestei metode reprezinta tocmai constructia interfetei grafice. Interfata de programare GWT (API) contine o famile de clase widget. O instanta a unui
widget se asociaza fantei prin
RootPanel.get("slot").add(widget);
Clasele widget cu metodele care vor fi utilizate sunt:
Label
Constructori:
2

widget=gadget virtual, gadget=dispozitiv amuzant, fara nsemnatate practica.

148

CAPITOLUL 8. APLICAT
II WEB

Label()
Label(String text)
Metode:
public void setText(String text)
TextBox
Constructori:
TextBox()
Metode:
public String getText()
public void setText(String text)
public void setVisibleLength(int lungime)
Button
Constructori:
Button(String text)
Metode:
public HandlerRegistration addClickHandler(ClickHandler click
Handler )
Metoda clickHandler contine prelucrarea atasata butonului.
Containere de widget
VerticalPanel
VerticalSplitPanel
HorizontalPanel HorizontalSplitPanel
FlowPanel
DockPanel
Un widget se include ntr-un container cu metoda
void add(Widget widget)
3. Generarea evenimentelor. Activitatile / actiunile care constituie obiectivul aplicatiei
GWT se lanseaza printr-un clic pe un buton. Fiecarui buton i se atribuie un obiect
care implementeaza interfata ClickHandler. Activitatile amintite mai sus sunt
definite n codul metodei public void onClick(ClickEvent event).
4. Programarea activitatilor corespunzatoare evenimentelor atasate butoanelor, adica
implementarea metodelor onClick.
5. Fixarea elementelor de stil ale elementelor grafice n fisierul MyApp.css. Atasarea la
un widget a unui element de stil se obtine cu metoda public void addStyleName(
String style).
Urmarim acesti pasi n
Exemplul 8.3.1 Calculul unei integrale. Transformam aplicatia 1.2 ntr-o aplicatie GWT.

8.3. GOOGLE WEB TOOLKIT (GWT)

149

Intr-o aplicatie GWT codurile Java din catalogul client sunt transformate n cod
JavaScript. Drept consecinta, nu se pot utiliza arhive jar. In locul lor, se vor folosi
module GWT, care n cazul aplicatiei de fata sunt:
mini-biblioteca mathlib, pentru calculul propriu-zis al integralei. Mini-biblioteca
mathlib a fost organizata de la nceput ca modul GWT;
MathEclipse-Parser, pentru evaluarea expresiilor de calcul date ca String.
Clasa mathlib.client.cvadra.MEParserDataIn, parte a mini-bibliotecii mathlib, extinde
clasa abstracta mathlib.client.cvadra.DataIn:
1
2
4
5
6
7

package m a t h l i b . c l i e n t . c v a d r a ;
import o r g . m a t h e c l i p s e . p a r s e r . c l i e n t . e v a l . ;
public c l a s s MEParserDataIn extends DataIn {
private D o u b l e E v a l u a t o r p a r s e r=n u l l ;
private ID ou bl eVa lu e v=n u l l ;
private S t r i n g e x p r ;
public void setA ( S t r i n g e x p r ) {
D o u b l e E v a l u a t o r a P a r s e r=new D o u b l e E v a l u a t o r ( ) ;
super . setA ( a P a r s e r . e v a l u a t e ( e x p r ) ) ;
}
public void setB ( S t r i n g e x p r ) {
D o u b l e E v a l u a t o r b P a r s e r=new D o u b l e E v a l u a t o r ( ) ;
super . setB ( b P a r s e r . e v a l u a t e ( e x p r ) ) ;
}

9
10
11
12
13
14
15
16

public MEParserDataIn ( S t r i n g var , S t r i n g e x p r ) {


t h i s . e x p r=e x p r ;
p a r s e r=new D o u b l e E v a l u a t o r ( ) ;
v=new D o u b l e V a r i a b l e ( 0 . 0 ) ;
p a r s e r . d e f i n e V a r i a b l e ( var , v ) ;
}

18
19
20
21
22
23

// f u n c t i a de i n t e g r a t
public double f c t ( double x ) {
v . setValue (x ) ;
return p a r s e r . e v a l u a t e ( e x p r ) ;
}

25
26
27
28
29
30

Concret se vor copia unele cataloage din sursa mini-bibliotecii si din fisierele sursa
obtinute din dezarhivarea fisierului matheclipse-parser-*.jar.
Se genereaza proiectului GWT cu punctul de intrare dat de clasa numerjava.gwt.
AppIntegrala. Structura generata de cataloage si fisiere se completeaza cu resursele
indicate n Fig. 8.2.
Proiectarea interfetei grafice. Consideram interfeta grafica
Calculul unei integrale Label titleLabel
HorizontalPanel hp
Panou container pentru dataPanel si resultsPanel
VerticalPanel dataPanel
Panoul stang pentru datele furnizate de client
VerticalPanel resultsPanel
Panou drept pentru rezultatele aplicatiei
Integreaza
Button button

150

CAPITOLUL 8. APLICAT
II WEB

integrala
|--> src
|
|--> numerjava
|
|
|--> gwt
|
|
|
|--> client
|
|
|
|
|
AppIntegrala.java
|
|
|
|
|
. . .
|
|
|
|
AppIntegrala.gwt.xml
|
|--> mathlib
|
|
|--> client
|
|
|
|--> cvadra
|
|
|
|
|--> impl
|
|
|
|
|
|
MetodaSimpsonWeb.java
|
|
|
|
|
IMetodaSimpson.java
|
|
|
|
|
DataIn.java
|
|
|
|
|
DataOut.java
|
|
|
|
|
MEParserDataIn.java
|
|
|
Mathlib.gwt.xml
|
|--> org
|
|
|--> matheclipse
|
|
|
|--> parser
|
|
|
|
|
. . .
|
|
. . .
|
|--> war
|
|
|--> WEB-INF
|
|
|
|
. . .
|
|
|
MyApp.css
|
|
|
MyApp.html
|
. . .

Fig. 8.2: Initializarea unei aplicatii GWT.


unde panourile dataPanel si resultsPanel contin
Label varLabel
TextBox varTextBox
pentru introducerea simbolului variabilei de integrare
Functia
Label exprLabel
TextBox exprTextBox
pentru introducerea expresiei de integrat
Limita inferioara
Label infLabel
TextBox infTextBox
pentru introducerea limitei inferioara a intervalului
Limita superioara
Label supLabel
TextBox supTextBox
pentru introducerea limitei superioare a intervalului
Toleranta
Label epsLabel
TextBox epsTextBox
pentru introducerea tolerantei
Numar maxim admis de iteratii Label nmiLabel
TextBox nmiTextBox
pentru introducerea numarului maxim admis de iteratii
Simbolul variabilei

si respectiv

8.3. GOOGLE WEB TOOLKIT (GWT)

151

Indicatorul de raspuns
Label indLabel
Integrala
Label integLabel
Numarul de iteratii efectuat Label niLabel
Widgetele titleLabel, hp, button vor fi redate n fantele declarate respectiv prin
<body class="bd">
<center>
<div id="titleLabel"> </div>
<p><div id="mainPanel"></div></p>
<p><div id="button"></div></p>
</center>
</body>

Construirea interfetei grafice. Codul care implementeaza interfata grafica imaginata


mai sus este
public void onModuleLoad() {
Label titleLabel=new Label("Calculul unei integrale");
Label varLabel=new Label("Simbolul variabilei");
Label exprLabel=new Label("Functia");
Label infLabel=new Label("Limita inferiara");
Label supLabel=new Label("Limita superioara");
Label epsLabel=new Label("Toleranta");
Label nmiLabel=new Label("Numar maxim admis de iteratii");
TextBox varTextBox=new TextBox();
varTextBox.setVisibleLength(20);
TextBox exprTextBox=new TextBox();
exprTextBox.setVisibleLength(20);
TextBox infTextBox=new TextBox();
infTextBox.setVisibleLength(20);
TextBox supTextBox=new TextBox();
supTextBox.setVisibleLength(20);
TextBox epsTextBox=new TextBox();
epsTextBox.setVisibleLength(20);
epsTextBox.setText("1e-5");
TextBox nmiTextBox=new TextBox();
nmiTextBox.setText("50");
nmiTextBox.setVisibleLength(20);
VerticalPanel dataPanel=new VerticalPanel();
dataPanel.add(varLabel);
dataPanel.add(varTextBox);
dataPanel.add(exprLabel);
dataPanel.add(exprTextBox);
dataPanel.add(infLabel);
dataPanel.add(infTextBox);
dataPanel.add(supLabel);
dataPanel.add(supTextBox);
dataPanel.add(epsLabel);
dataPanel.add(epsTextBox);
dataPanel.add(nmiLabel);
dataPanel.add(nmiTextBox);
dataPanel.setBorderWidth(2);
Label indLabel=new Label("Indicatorul de raspuns");
Label integLabel=new Label("Integrala");
Label niLabel=new Label("Numarul de iteratii efectuat");
VerticalPanel resultsPanel=new VerticalPanel();
resultsPanel.add(indLabel);
resultsPanel.add(integLabel);
resultsPanel.add(niLabel);
resultsPanel.setBorderWidth(2);
HorizontalPanel hp=new HorizontalPanel();
hp.setSpacing(10);
hp.add(dataPanel);
hp.add(resultsPanel);

152

CAPITOLUL 8. APLICAT
II WEB

Button button=new Button("Integreaza");


RootPanel.get("titleLabel").add(titleLabel);
RootPanel.get("mainPanel").add(hp);
RootPanel.get("button").add(button);
}
}

Generarea evenimentelor. Butonului i se asociaza o instanta a clasei MyClickHandler, care contine actiunile executate dupa clic pe buton.
MyClickHandler handler=new MyClickHandler(varTextBox,
exprTextBox,infTextBox,supTextBox,epsTextBox,nmiTextBox,
indLabel,integLabel,niLabel);
button.addClickHandler(handler);

Programarea activitatilor corespunzatoare evenimentelor. Acest pas corespunde realizarii clasei MyClickHandler. Actiunile care se executa constau din verificarea completarii fiecarui camp al formularului, urmata de calculul integralei.
Codul clasei MyClickHandler este
1
2
3
4
5
6
7
8
9
10
12
13
14
15
16
17
18
19
20
21
22
23
24
25
27
28
29
30
31
32
33
34
35
36
37
39
40
41
42
43

c l a s s MyClickHandler implements C l i c k H a n d l e r {
TextBox varTextBox ;
TextBox exprTextBox ;
TextBox i n f T e x t B o x ;
TextBox supTextBox ;
TextBox epsTextBox ;
TextBox nmiTextBox ;
Label indLabel ;
Label i n t e g L a b e l ;
Label niLabel ;
MyClickHandler ( TextBox varTextBox , TextBox exprTextBox ,
TextBox infTextBox , TextBox supTextBox ,
TextBox epsTextBox , TextBox nmiTextBox ,
Label indLabel , Label integLabel , Label niLabel ){
t h i s . varTextBox=varTextBox ;
t h i s . exprTextBox=exprTextBox ;
t h i s . i n f T e x t B o x=i n f T e x t B o x ;
t h i s . supTextBox=supTextBox ;
t h i s . epsTextBox=epsTextBox ;
t h i s . nmiTextBox=nmiTextBox ;
t h i s . i n d L a b e l=i n d L a b e l ;
t h i s . i n t e g L a b e l=i n t e g L a b e l ;
t h i s . n i L a b e l=n i L a b e l ;
}
public boolean i s C o m p l e t e d ( TextBox tb , S t r i n g name ) {
S t r i n g t x t=tb . g e t T e x t ( ) ;
i f ( txt . equals ( ) ) {
Window . a l e r t ( Camp n e c o m p l e t a t : +name ) ;
indLabel . setText ( ? ) ;
integLabel . setText ( ? ) ;
niLabel . setText ( ? ) ;
return f a l s e ;
}
return true ;
}
public void o n C l i c k ( C l i c k E v e n t e v e n t ) {
i f ( ! i s C o m p l e t e d ( varTextBox , S i m b o l u l v a r i a b i l e i ) ) return ;
i f ( ! i s C o m p l e t e d ( exprTextBox , F u n c t i a ) ) return ;
i f ( ! i s C o m p l e t e d ( infTextBox , L i m i t a i n f e r i o a r a ) ) return ;
i f ( ! i s C o m p l e t e d ( supTextBox , L i m i t a s u p e r i o a r a ) ) return ;

8.3. GOOGLE WEB TOOLKIT (GWT)

i f ( ! i s C o m p l e t e d ( epsTextBox , T o l e r a n t a ) ) return ;
i f ( ! i s C o m p l e t e d ( nmiTextBox , Numar maxim admin de i t e r a t i i ) ) return ;
MEParserDataIn d i n=
new MEParserDataIn ( varTextBox . g e t T e x t ( ) , exprTextBox . g e t T e x t ( ) ) ;
d i n . setA ( i n f T e x t B o x . g e t T e x t ( ) ) ;
d i n . setB ( supTextBox . g e t T e x t ( ) ) ;
S t r i n g e p s=epsTextBox . g e t T e x t ( ) ;
S t r i n g nmi=nmiTextBox . g e t T e x t ( ) ;
d i n . s e t E p s ( Double . p a r s e D o u b l e ( e p s ) ) ;
d i n . setNmi ( I n t e g e r . p a r s e I n t ( nmi ) ) ;
IMetodaSimpson o b j=new MetodaSimpsonWeb ( ) ;
DataOut dout=o b j . metodaSimpson ( d i n ) ;
i n d L a b e l . s e t T e x t ( I n d i c a t o r u l de r a s p u n s : +dout . g e t I n d ( ) ) ;
i n t e g L a b e l . s e t T e x t ( I n t e g r a l a : +
NumberFormat . getFormat ( ###0.000000 ) . f o r m a t ( dout . g e t I n t e g r a l a ( ) ) ) ;
n i L a b e l . s e t T e x t ( Numarul i t e r a t i i l o r e f e c t u a t e : +dout . g e t N i ( ) ) ;

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

60
61

Fixarea elementelor de stil. Fisierul AppIntegrala.css contine


.button {
display: block;
font-size: 18pt;
color: blue
}
.label-title {
font-weight: bold;
font-size: 20pt;
color: blue
}
.bd{
background-color: #bbccbb;
}

Codul complet al clasei AppIntegrala.java este


1

package numerjava . gwt . c l i e n t ;

10

import
import
import
import
import
import
import
import

12

public c l a s s A p p I n t e g r a l a implements E n t r y P o i n t {

4
5
6
7
8
9

14
15
16
17
18
19
20
21
22
23
24
25
26

com . g o o g l e . gwt . c o r e . c l i e n t . E n t r y P o i n t ;
com . g o o g l e . gwt . u s e r . c l i e n t . u i . ;
com . g o o g l e . gwt . u s e r . c l i e n t . Window ;
com . g o o g l e . gwt . i 1 8 n . c l i e n t . NumberFormat ;
com . g o o g l e . gwt . e v e n t . dom . c l i e n t . C l i c k E v e n t ;
com . g o o g l e . gwt . e v e n t . dom . c l i e n t . C l i c k H a n d l e r ;
mathlib . c l i e n t . cvadra . ;
m a t h l i b . c l i e n t . c v a d r a . impl . MetodaSimpsonWeb ;

public void onModuleLoad ( ) {


L a b e l t i t l e L a b e l=new L a b e l ( C a l c u l u l u n e i i n t e g r a l e ) ;
t i t l e L a b e l . addStyleName ( l a b e l t i t l e ) ;
L a b e l v a r L a b e l=new L a b e l ( S i m b o l u l v a r i a b i l e i ) ;
L a b e l e x p r L a b e l=new L a b e l ( F u n c t i a ) ;
L a b e l i n f L a b e l=new L a b e l ( L i m i t a i n f e r i a r a ) ;
L a b e l s u p L a b e l=new L a b e l ( L i m i t a s u p e r i o a r a ) ;
L a b e l e p s L a b e l=new L a b e l ( T o l e r a n t a ) ;
L a b e l nmiLabel=new L a b e l ( Numar maxim admis de i t e r a t i i ) ;
TextBox varTextBox=new TextBox ( ) ;
varTextBox . s e t V i s i b l e L e n g t h ( 2 0 ) ;
TextBox exprTextBox=new TextBox ( ) ;
exprTextBox . s e t V i s i b l e L e n g t h ( 2 0 ) ;

153

154

CAPITOLUL 8. APLICAT
II WEB

TextBox i n f T e x t B o x=new TextBox ( ) ;


infTextBox . s e t V i s i b l e L e n g t h ( 2 0 ) ;
TextBox supTextBox=new TextBox ( ) ;
supTextBox . s e t V i s i b l e L e n g t h ( 2 0 ) ;
TextBox epsTextBox=new TextBox ( ) ;
epsTextBox . s e t V i s i b l e L e n g t h ( 2 0 ) ;
epsTextBox . s e t T e x t ( 1 e5 ) ;
TextBox nmiTextBox=new TextBox ( ) ;
nmiTextBox . s e t T e x t ( 50 ) ;
nmiTextBox . s e t V i s i b l e L e n g t h ( 2 0 ) ;

27
28
29
30
31
32
33
34
35
36

V e r t i c a l P a n e l d a t a P a n e l=new V e r t i c a l P a n e l ( ) ;
d a t a P a n e l . add ( v a r L a b e l ) ;
d a t a P a n e l . add ( varTextBox ) ;
d a t a P a n e l . add ( e x p r L a b e l ) ;
d a t a P a n e l . add ( exprTextBox ) ;
d a t a P a n e l . add ( i n f L a b e l ) ;
d a t a P a n e l . add ( i n f T e x t B o x ) ;
d a t a P a n e l . add ( s u p L a b e l ) ;
d a t a P a n e l . add ( supTextBox ) ;
d a t a P a n e l . add ( e p s L a b e l ) ;
d a t a P a n e l . add ( epsTextBox ) ;
d a t a P a n e l . add ( nmiLabel ) ;
d a t a P a n e l . add ( nmiTextBox ) ;
d a t a P a n e l . setBorderWidth ( 2 ) ;

38
39
40
41
42
43
44
45

L a b e l i n d L a b e l=new L a b e l ( I n d i c a t o r u l de r a s p u n s ) ;
L a b e l i n t e g L a b e l=new L a b e l ( I n t e g r a l a ) ;
L a b e l n i L a b e l=new L a b e l ( Numarul de i t e r a t i i e f e c t u a t ) ;

47
48
49

V e r t i c a l P a n e l r e s u l t s P a n e l=new V e r t i c a l P a n e l ( ) ;
r e s u l t s P a n e l . add ( i n d L a b e l ) ;
r e s u l t s P a n e l . add ( i n t e g L a b e l ) ;
r e s u l t s P a n e l . add ( n i L a b e l ) ;
r e s u l t s P a n e l . setBorderWidth ( 2 ) ;

51
52
53
54
55

H o r i z o n t a l P a n e l hp=new H o r i z o n t a l P a n e l ( ) ;
hp . s e t S p a c i n g ( 1 0 ) ;
hp . add ( d a t a P a n e l ) ;
hp . add ( r e s u l t s P a n e l ) ;

57
58
59
60

Button b ut to n=new Button ( I n t e g r e a z a ) ;


b ut to n . addStyleName ( b ut to n ) ;
MyClickHandler h a n d l e r=new MyClickHandler ( varTextBox ,
exprTextBox , infTextBox , supTextBox , epsTextBox , nmiTextBox ,
indLabel , integLabel , niLabel ) ;
b ut to n . a d d C l i c k H a n d l e r ( h a n d l e r ) ;

62
63
64
65
66
67

RootPanel . g e t ( t i t l e L a b e l ) . add ( t i t l e L a b e l ) ;
RootPanel . g e t ( mainPanel ) . add ( hp ) ;
RootPanel . g e t ( b ut to n ) . add ( but t on ) ;

69
70
71

72
73

75

c l a s s MyClickHandler implements C l i c k H a n d l e r {
TextBox varTextBox ;
TextBox exprTextBox ;
TextBox i n f T e x t B o x ;
TextBox supTextBox ;
TextBox epsTextBox ;
TextBox nmiTextBox ;
Label indLabel ;
Label i n t e g L a b e l ;
Label niLabel ;

76
77
78
79
80
81
82
83
84
86
87
88
89
90
91
92
93

MyClickHandler ( TextBox varTextBox , TextBox exprTextBox , TextBox infTextBox ,


TextBox supTextBox , TextBox epsTextBox , TextBox nmiTextBox ,
Label indLabel , Label integLabel , Label niLabel ){
t h i s . varTextBox=varTextBox ;
t h i s . exprTextBox=exprTextBox ;
t h i s . i n f T e x t B o x=i n f T e x t B o x ;
t h i s . supTextBox=supTextBox ;
t h i s . epsTextBox=epsTextBox ;

URAREA IN NOR
8.4. DESFAS

t h i s . nmiTextBox=nmiTextBox ;
t h i s . i n d L a b e l=i n d L a b e l ;
t h i s . i n t e g L a b e l=i n t e g L a b e l ;
t h i s . n i L a b e l=n i L a b e l ;

94
95
96
97

98

public boolean i s C o m p l e t e d ( TextBox tb , S t r i n g name ) {


S t r i n g t x t=tb . g e t T e x t ( ) ;
i f ( txt . equals ( ) ) {
Window . a l e r t ( Camp n e c o m p l e t a t : +name ) ;
indLabel . setText ( ? ) ;
integLabel . setText ( ? ) ;
niLabel . setText ( ? ) ;
return f a l s e ;
}
return true ;
}

100
101
102
103
104
105
106
107
108
109
110

public void o n C l i c k ( C l i c k E v e n t e v e n t ) {
i f ( ! i s C o m p l e t e d ( varTextBox , S i m b o l u l v a r i a b i l e i ) ) return ;
i f ( ! i s C o m p l e t e d ( exprTextBox , F u n c t i a ) ) return ;
i f ( ! i s C o m p l e t e d ( infTextBox , L i m i t a i n f e r i o a r a ) ) return ;
i f ( ! i s C o m p l e t e d ( supTextBox , L i m i t a s u p e r i o a r a ) ) return ;
i f ( ! i s C o m p l e t e d ( epsTextBox , T o l e r a n t a ) ) return ;
i f ( ! i s C o m p l e t e d ( nmiTextBox , Numar maxim admin de i t e r a t i i ) ) return ;
MEParserDataIn d i n=new MEParserDataIn ( varTextBox . g e t T e x t ( ) , exprTextBox . g e t T e x t ( ) ) ;
d i n . setA ( i n f T e x t B o x . g e t T e x t ( ) ) ;
d i n . setB ( supTextBox . g e t T e x t ( ) ) ;
S t r i n g e p s=epsTextBox . g e t T e x t ( ) ;
S t r i n g nmi=nmiTextBox . g e t T e x t ( ) ;
d i n . s e t E p s ( Double . p a r s e D o u b l e ( e p s ) ) ;
d i n . setNmi ( I n t e g e r . p a r s e I n t ( nmi ) ) ;
IMetodaSimpson o b j=new MetodaSimpsonWeb ( ) ;
DataOut dout=o b j . metodaSimpson ( d i n ) ;
i n d L a b e l . s e t T e x t ( I n d i c a t o r u l de r a s p u n s : +dout . g e t I n d ( ) ) ;
i n t e g L a b e l . s e t T e x t ( I n t e g r a l a : +
NumberFormat . getFormat ( ###0.000000 ) . f o r m a t ( dout . g e t I n t e g r a l a ( ) ) ) ;
n i L a b e l . s e t T e x t ( Numarul i t e r a t i i l o r e f e c t u a t e : +dout . g e t N i ( ) ) ;
}

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

155

Continutul fisierului de configurare al modulului mathlib (Mathlib.gwt.xml ) este


<module>
<inherits name="com.google.gwt.user.User"/>
<inherits name="org.matheclipse.parser.Parser"/>
</module>

iar fisierul AppIntegrala.gwt.xml se completeaza cu


<inherits name="org.matheclipse.parser.Parser"/>
<inherits name="mathlib.Mathlib"/>

Interfata grafica a aplicatiei este prezentata n Fig. 8.3.

8.4

Desf
asurarea n nor

Dezvoltarea Internetului, nevoia de a reduce costurile legate de realizarea si ntretinerea


infrastructurii care ofera servicii pe Internet, concomitent cu nevoia de crestere a calitatii
serviciilor a condus la servicii n nor (Cloud Computing).
Avantajele oferite de serviciile serviciile n nor sunt:

156

CAPITOLUL 8. APLICAT
II WEB

Fig. 8.3: Aplicatia GWT AppIntegrala.


Reducerea costurilor
Agilitate (Agility)
Reducerea duratei:
de asteptare n cazul aparitiei unei disfunctionalitati din partea furnizorului
serviciului n nor;
de actualizare si ntretinere din partea realizatorului serviciului n nor.
Elasticitate (Elasticity)
Posibilitatea de crestere / descrestere a resurselor (n principal hard) alocate pentru
a satisface cerintele clientilor ntr-un interval de timp.
Se face distinctie de scalabilitate, termen care desemneaza nevoia de cresere / descrestere a resurselor alocate legata de dezvoltarea aplicatiilor care compun serviciul.
Tipuri de servicii n nor:
Aplicatii ca serviciu (Software as a Service - SaaS )
Skype, Googles Docs, Gmail, Yahoo Messenger, Microsoft Office 365, etc.
Infrastructura ca serviciu (Infrastructure as a Service - IaaS )
Amazons Elastic Compute Cloud - (EC2)

URAREA IN NOR
8.4. DESFAS

157

Plaforma ca serviciu (Platform as a Service - PaaS )


PaaS poate fi
Ne-portabla : aplicatia va avea o structura predefinita.
Google AppEngine (GAE), Microsoft Azure, OpenShift
Portabila
Heroku
In cele ce urmeaza ne intereseaza doar platformele PaaS care accepta desfasurarea de
aplicatii Java, n mod gratuit (cel putin pentru un numar redus de aplicatii), sau ofera
un simulator local. Serviciile n nor Google AppEngine, Heroku, OpenShift asigura aceste
conditii. Modul de tratare este specifica fiecarui serviciu n nor n parte.
Vom exemplifica doar utilizarea simulatorului pentru Google App Engine (GAE) care
permite
ncarcarea unei aplicatii Web pe un simulator local al platformei de Cloud Computing;
ncarcarea unei aplicatii Web pe platforma Google de Cloud Computing.
In prezent, pe platforma GAE se pot ncarca aplicatii realizate n Java, Python, PHP
si Go, alaturi de care care pot aparea fisiere http, css, js. Exista cate o distributie distincta
pentru fiecare din aceste limbaje de programare.
Versiunea GAE pentru Java necesita Java 7 si servlet-api 2.5.

Utilizarea simulatorului local


Distributia GAE pentru Java contine sablonul unei aplicatii (appengine-java-sdk-*\
demos\new project template) mpreuna cu un fisier build.xml prin intermediul caruia,
cu ajutorul lui apache-ant, se construieste aplicatia n vederea verificarii pe simulator /
ncarcarii n nor.
Programatorul va nlocui aplicatia din sablon cu propria aplicatie, eventual va face
adaptarile necesare si va rula apache-ant.
Lansarea simulatorului se poate face prin comenzile
set GAE\_HOME=. . .\appengine-java-sdk-*
%GAE\_HOME%\bin\dev_appserver war

lansate ntr-o fereasta DOS, n catalogul care contine catalogul war. Aplicatia se apeleaza
prin http://localhost:8080. Daca n loc de index.html se utilizeaza alt nume, atunci
apelarea aplicatiei este
http://localhost:8080/fi
sier.html.
Exemplul 8.4.1 Integrarea servlet-ului MetodaSimpsonServet, dezvoltata ntr-o sectiune
anterioara, n platforma Google App Engine.

158

CAPITOLUL 8. APLICAT
II WEB

Sablonul aplicatiei se copiaza ntr-o zona de lucru sub numele appintegrala si se completeaza cu fisierele servlet-ului (MetodaSimpsonServlet.java, index.html ) si catalogul lib.
Rezultatul va fi
appintegrala
|--> src
|
|--> integrala
|
|
|
MetodaSimpsonServlet.java
|
|--> META-INF
|
|
|
. . .
|
|
log4j.properties
|
|
logging.properties
|
|--> WEB-INF
|
|
|--> lib
|
|
|
|
jep-2.4.1.jar
|
|
|
|
mathlib.jar
|
|
|
appengine-web.xml
|
|
|
web.xml
|
|
index.html
|
build.xml

Singurul fisier specific GAE este appengine-web.xml, dar adaptarea acestuia se face
doar pentru ncarcarea n nor.

Capitolul 9
Inc
arcarea unui fisier - upload
Problema pe care o tratam consta n transferul unui volum mare de date ale clientului
catre aplicatia server. In particular, consideram cazul n care datele corespund unei
matrice.
La nceput vom distinge cazul n care matricea are dimensiuni rezonabile, putand fi
introdusa ntr-o pagina html. In acest scop se vor utiliza functii Javascript.
In cazul n care volumul datelor de preluat de catre aplicatia Web este mare, calea de
urmat consta din:
1. Scrierea / depozitarea datelor ntr-un fisier;
2. Incarcarea fisierului n aplicatia Web.
Expedierea datelor dintr-un fisier si receptionarea lor defineste problema ncarcarii unui
fisier (file upload ). Un produs care ne ajuta sa ndeplinim acest obiectiv este pachetul
commons-fileupload - dezvoltat de apache.

9.1

Preluarea unei matrice prin functii Javascript

Preluarea elementelor unei matrice sau vector de dimensiune redusa, necesare unei
aplicatii Web, se poate programa n mod elegant utilizand functii Javascript. Exemplificam prin
Exemplul 9.1.1 Preluarea si transmiterea unei matrice la un servlet.
Pentru nceput se preiau ntr-un formular html numarul liniilor si ale coloanelor.
1
2
3
4
5
6
7
8
9
10
11

< ! doctype html>


<head>
< t i t l e> MatrixEnterForm </ t i t l e>
<s c r i p t type= t e x t / j a v a s c r i p t >
< !
function initRequest () {
i f ( window . XMLHttpRequest ) {
r e t u r n new XMLHttpRequest ( ) ;
} e l s e i f ( window . A c t i v e X O b j e c t ) {
r e t u r n new A c t i v e X O b j e c t ( M i c r o s o f t .XMLHTTP ) ;
}

159

160

CAPITOLUL 9. INCARCAREA
UNUI FIS
IER - UPLOAD

12

14

f u n c t i o n compute ( ) {
var mField=document . g e t E l e m e n t B y I d ( rows ) ;
var n F i e l d=document . g e t E l e m e n t B y I d ( c o l s ) ;
var u r l = / j s m a t r i x / m a t r i x ?m= +
e s c a p e ( mField . value)+&n=+e s c a p e ( n F i e l d . value)+&mat=+e s c a p e ( a r r a y 2 S t r i n g ( ) ) ;
var r e q = i n i t R e q u e s t ( ) ;
req . onreadystatechange = function () {
i f ( r e q . r e a d y S t a t e == 4) {
i f ( r e q . s t a t u s == 200) {
p a r s e M e s s a g e s ( r e q . responseXML ) ;
} else {
a l e r t ( r e q . s t a t u s+ : +r e q . s t a t u s T e x t ) ;
}
}
};
r e q . open ( g e t , u r l , t r u e ) ;
r e q . send ( n u l l ) ;
}

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
67
68
69
70
71
72
73
74
75
76
77
78

f u n c t i o n p a r s e M e s s a g e s ( responseXML ) {
var r = responseXML . getElementsByTagName ( r e z u l t a t ) [ 0 ] ;
document . g e t E l e m e n t B y I d ( r e z u l t a t ) . innerHTML= ;
f o r ( i =0; i<r . c h i l d N o d e s . l e n g t h ; i ++){
document . getElementById ( r e z u l t a t ) . innerHTML=
document . getElementById ( r e z u l t a t ) . innerHTML+<br/> ;
var row=r . c h i l d N o d e s [ i ] ;
f o r ( j =0; j <row . c h i l d N o d e s . l e n g t h ; j ++){
var c o l=row . getElementsByTagName ( c o l ) [ j ] ;
var t=c o l . c h i l d N o d e s [ 0 ] . nodeValue ;
document . getElementById ( r e z u l t a t ) . innerHTML=
document . getElementById ( r e z u l t a t ) . innerHTML+t+ ;
}
}
}
function templateMatrix (){
var rows=document . myForm . rows . value ;
var c o l s=document . myForm . c o l s . value ;
var myInput= ;
document . getElementById ( m a t r i x ) . innerHTML= ;
f o r ( var i =0; i <rows ; i ++){
myInput=<br/> ;
document . getElementById ( m a t r i x ) . innerHTML=
document . getElementById ( m a t r i x ) . innerHTML+myInput ;
f o r ( var j =0; j <c o l s ; j ++){
myInput=<i n p u t t y p e =number s t e p =any name= mat +i+
+j+ s i z e = 5 i d = mat +i+ +j+ /> ;
document . getElementById ( m a t r i x ) . innerHTML=
document . getElementById ( m a t r i x ) . innerHTML+myInput ;
}
}
}
function array2String (){
var rows=document . myForm . rows . value ;
var c o l s=document . myForm . c o l s . value ;
var x=new Array ( rows ) ;
f o r ( var i =0; i <rows ; i ++){
x [ i ]=new Array ( c o l s )
f o r ( var j =0; j <c o l s ; j ++){
x [ i ] [ j ]= p a r s e F l o a t ( document . getElementById ( mat +i+ +j ) . value ) ;
}
}
return x . toString ( ) ;
}

9.1. PRELUAREA UNEI MATRICE PRIN FUNCT


II JAVASCRIPT

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

161

//>
</ s c r i p t>
</head>
<body>
<h1> Matrix Enter Form </h1>
<br/>
<form name=myForm>
<table>
<tr>
<td> Rows </td>
<td>
<input type=number id= rows name= rows s i z e= 10 r e q u i r e d min= 1 />
</td>
</ tr>
<tr>
<td> Columns </td>
<td>
<input type=number id= c o l s name= c o l s s i z e= 10 r e q u i r e d min= 1 />
</td>
</ tr>
<tr>
<td></td>
<td>
<input type= b ut to n onClick= t e m p l a t e M a t r i x ( )
name= m a t r i x value= G e n e r a t e a r r a y />
</td>
</ tr>
</ table>
<div id= m a t r i x > </ div>
<p/>
<input type= b ut to n value= C a l c u l e a z a onClick= compute ( ) >
</form>
<div id= r e z u l t a t ></ id>
</body>
</html>

Containerul care va contine sablonul matricei este


<div id="matrix"> </div>

Functia Javascript templateMatrix nscrie n container sablonul matricei, adica cate un


camp de introducere date pentru fiecare element al matricei. Generarea sablonului are
loc la actionarea butonului Generate array.
Pe partea de server, preluarea datelor se realizeaza printr-o aplicatie de tip servlet a
carei singura actiune este afisarea datelor receptionate.
Transmisia dintre clientul Web si server se realizeaza prin tehnologia Asynchronous
JavaScript And Xml (AJAX).
Codul servlet-ului este
1
2
3
4
5
7
8
9
10
11
13
14

package m a t r i x ;
import j a v a . i o . ;
import j a v a x . s e r v l e t . ;
import j a v a x . s e r v l e t . h t t p . ;
import j a v a x . s e r v l e t . a n n o t a t i o n . WebServlet ;
@WebServlet ( u r l P a t t e r n s = / m a t r i x )
public f i n a l c l a s s R e a d M a t r i x S e r v l e t extends H t t p S e r v l e t {
public void doGet ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )
throws S e r v l e t E x c e p t i o n , IOException {
P r i n t W r i t e r out=r e s . g e t W r i t e r ( ) ;
S t r i n g rows=r e q . g e t P a r a m e t e r ( m ) ;
i n t m=I n t e g e r . p a r s e I n t ( rows ) ;

162

CAPITOLUL 9. INCARCAREA
UNUI FIS
IER - UPLOAD

S t r i n g c o l s=r e q . g e t P a r a m e t e r ( n ) ;
i n t n=I n t e g e r . p a r s e I n t ( c o l s ) ;
S t r i n g mat=r e q . g e t P a r a m e t e r ( mat ) ;
double [ ] [ ] t=new double [m ] [ n ] ;
S t r i n g [ ] s=mat . s p l i t ( , ) ;
f o r ( i n t i =0; i <m; i ++)
f o r ( i n t j =0; j <n ; j ++)
t [ i ] [ j ]= Double . p a r s e D o u b l e ( s [ i n+j ] ) ;
r e s . setContentType ( t e x t /xml ) ;
r e s . s e t H e a d e r ( CacheC o n t r o l , noc a c h e ) ;
out . p r i n t ( <?xml v e r s i o n =\1.0\ ?> ) ;
out . p r i n t ( <r e z u l t a t > ) ;
f o r ( i n t i =0; i <m; i ++){
out . p r i n t ( <row> ) ;
f o r ( i n t j =0; j <n ; j ++){
out . p r i n t ( <c o l > ) ;
out . p r i n t (new Double ( t [ i ] [ j ] ) . t o S t r i n g ( ) ) ;
out . p r i n t ( </ c o l > ) ;
}
out . p r i n t ( </row> ) ;
}
out . p r i n t ( </ r e z u l t a t > ) ;
out . c l o s e ( ) ;

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

40

public void doPost ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )


throws S e r v l e t E x c e p t i o n , IOException {
doGet ( req , r e s ) ;
}

41
42
43
44

9.2

FileUpload

Transferarea unui fisier, din partea clientului nu ridica nicio problema. In fisierul html
de apelare (client Web) se defineste un formular
<form
action=. . .
enctype="multipart/form-data"
method="post">
iar un fisier de ncarcat se fixeaza prin intermediul marcajului
<input type="file" name=. . . size=. . .>
Programul navigator afiseaza o fereastra de cautare, prin care clientul selecteaza fisierul
pe care doreste sa-l ncarce.
1
2
3
4
5
6
7
8
9
10

< ! doctype html>


<body>
<center>
<h1> R e z o l v a r e a unui s i s t e m a l g e b r i c de ecua &#355; i i l i n i a r e </h1>
<form
action= / l i n e a r / l i n e a r
e n c t y p e= m u l t i p a r t / formdata
method= p o s t >
<h3> I n t r o d u c e &#355; i f i &#351; i e r u l cu d a t e l e s i s t e m u l u i </h3>
<table>

163

9.2. FILEUPLOAD

11
12
13
14
15
16
17
18
19
20
21
22

<tr>
<td> <input type= f i l e name= m y f i l e s i z e =30 r e q u i r e d> </td>
</ tr>
<tr>
<td> <input type= submit value= Expediaza > </td>
</ tr>
</ table>
<input type= h id de n name= t i p value= t e x t / html >
</form>
</ center>
</body>
</html>

Daca partea de client este un program, atunci se utilizeaza commons-httpclient, prezentat n 8.1.2.
Pe partea serverului utilizam produsul apache Commons-FileUpload care simplifica
transferul unui fisier de la un client la un servlet.
Din distributia produsului fisierele commons-fileupload-*.jar, commons-io-*.jar se depun
n catalogul WEB-INF\lib al servlet-ului.
Programarea ncarcarii revine la:
1. Declararea pachetelor din commons-fileupload utilizate
import org.apache.commons.fileupload.disk.*;
import org.apache.commons.fileupload.servlet.*;
import org.apache.commons.fileupload.*;
2. Crearea unei fabrici pentru manipularea fisierelor pe disc
FileItemFactory factory = new DiskFileItemFactory();
3. Crearea unei unelte de ncarcare
ServletFileUpload

upload = new ServletFileUpload(factory);

4. Analiza (parsarea) mesajului furnizat de client


List fileItems = upload.parseRequest(req);
Fiecare element al listei implementeaza interfata FileItem.
Se pot fixa parametrii:
dimensiunea zonei de pe disc destinata datelor de ncarcat
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(maxMemorySize);
catalogul temporar de retinere a datelor de ncarcat
factory.setRepositoryPath(tempDirectory);

164

CAPITOLUL 9. INCARCAREA
UNUI FIS
IER - UPLOAD

sau direct
DiskFileItemFactory factory = new DiskFileItemFactory(
maxMemorySize, tempDirectory);
dimensiunea maxima a unui fisier
upload.setSizeMax(maxRequestSize);
5. Prelucrarea elementelor ncarcate
Iterator iter=fileItems.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
if (item.isFormField()) {
// Prelucrarea elementului item care corespunde unei
// date din formularul html care nu este de tip fisier
}
else{
// Prelucrarea elementului item de tip fisier
}
}
6. In cazul unui element care nu este de tip fisier putem obtine numele si valoarea
atributului furnizat de client
String name = item.getFieldName();
String value = item.getString();
7. In cazul unui fisier putem afla numele campului input cu type="file", numele
fisierului, dimensiunea fisierului
String fieldName = item.getFieldName();
String fileName = item.getName();
long sizeInBytes = item.getSize();
8. Daca dorim sa salvam fisierul pe calculatorul server atunci prelucrarea este
File uploadedFile = new File(...);
item.write(uploadedFile);
9. Daca datele fisierului se ncarca n memoria calculatorului atunci prelucrarea este
InputStream in = item.getInputStream();
//preluarea datelor din fluxul in
. . .
in.close();

9.2. FILEUPLOAD

165

Alternativ, datele se pot retine ca un sir de octeti prin


byte[] data = item.get();
Exemplul 9.2.1 Pentru rezolvarea sistemului algebric de ecuatii liniare Ax = b, A
Mm,n (R), b Rm se formeaza matricea [A, b] ale carei elemente se retin ntr-un fisier
text astfel ncat fiecare linie contine o linie a matricei, iar elementele sunt separate prin
spatii. Matricea se ncarca ntr-un servlet unde se va utiliza clasa RezolvitorScilab din
mini-biblioteca mathlib pentru rezolvarea sistemului.
In servlet, preluarea matricei se face apeland metodele unui obiect mathlib.client.linear.
DataIn introdus n 2.3. Servletul are codul
1
2
3
4
5
6
7
8
9
10
11
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

package l i n e a r ;
import j a v a . i o . ;
import j a v a x . s e r v l e t . ;
import j a v a x . s e r v l e t . h t t p . ;
import j a v a . u t i l . ;
import o r g . apache . commons . f i l e u p l o a d . d i s k . ;
import o r g . apache . commons . f i l e u p l o a d . s e r v l e t . ;
import o r g . apache . commons . f i l e u p l o a d . ;
import m a t h l i b . c l i e n t . l i n e a r . ;
import m a t h l i b . c l i e n t . l i n e a r . impl . R e z o l v i t o r S c i l a b ;
import j a v a . t e x t . DecimalFormat ;
public c l a s s S i s t e m L i n i a r S e r v l e t extends H t t p S e r v l e t {
public void doPost ( H t t p S e r v l e t R e q u e s t req , H t t p S e r v l e t R e s p o n s e r e s )
throws S e r v l e t E x c e p t i o n , IOException {
S t r i n g t i p= ;
S e r v l e t O u t p u t S t r e a m out=n u l l ;
DecimalFormat f=new DecimalFormat ( 0 . 0 0 0 0 E0 ) ;
try {
F i l e I t e m F a c t o r y f a c t o r y = new D i s k F i l e I t e m F a c t o r y ( ) ;
ServletFileUpload
up lo ad = new S e r v l e t F i l e U p l o a d ( f a c t o r y ) ;
L i s t i t e m s = u pl oa d . p a r s e R e q u e s t ( r e q ) ;
up lo ad . s e t S i z e M a x ( 1 0 0 0 0 0 0 ) ;
I t e r a t o r i t e r=i t e m s . i t e r a t o r ( ) ;
DataIn d i n=new DataIn ( ) ;
while ( i t e r . hasNext ( ) ) {
F i l e I t e m item = ( F i l e I t e m ) i t e r . n e x t ( ) ;
i f ( ! item . i s F o r m F i e l d ( ) ) {
InputStream i n=item . g e t I n p u t S t r e a m ( ) ;
InputStreamReader i s r =new InputStreamReader ( i n ) ;
B u f f e r e d R e a d e r br=new B u f f e r e d R e a d e r ( i s r ) ;
d i n . s e t M a t r i x ( br ) ;
br . c l o s e ( ) ;
isr . close ();
in . close ( ) ;
}
else {
S t r i n g name = item . getFieldName ( ) ;
i f ( name . e q u a l s ( t i p ) )
t i p=item . g e t S t r i n g ( ) ;
}
}
r e s . setContentType ( t i p ) ;
out = r e s . getOutputStream ( ) ;
I R e z o l v i t o r S c i l a b o b j=new R e z o l v i t o r S c i l a b ( ) ;
DataOut dout=o b j . r e z o l v i t o r S c i l a b ( d i n ) ;
double [ ] x=n u l l ;
double [ ] [ ] k=n u l l ;
i n t l =0 , c =0;

166

i f ( dout . g e t E C o m p a t i b i l ( ) ) {
x=dout . getX ( ) ;
k=dout . getK ( ) ;
l=x . l e n g t h ;
i f ( k!= n u l l ) c=k [ 0 ] . l e n g t h ;
}
i f ( t i p . e q u a l s ( t e x t / html ) ) {
out . p r i n t l n ( <html><body b g c o l o r=\#bbccbb \ > ) ;
out . p r i n t l n ( <c e n t e r > ) ;
out . p r i n t l n ( <h1> S o l u &#355; i a s i s t e m u l u i a l g e b r i c +
de ecua &#355; i i l i n i a r e </h1> ) ;
i f ( dout . g e t E C o m p a t i b i l ( ) ) {
out . p r i n t l n ( <t a b l e b o r d e r=1 c e l l s p a c i n g =5> ) ;
out . p r i n t l n ( <t r > ) ;
out . p r i n t l n ( <th> X= </th> ) ;
out . p r i n t l n ( <th a l i g n =\ c e n t e r \ c o l s p a n=+(c 1)+> Ker= </th> ) ;
out . p r i n t l n ( </t r > ) ;
f o r ( i n t i =0; i <l ; i ++){
out . p r i n t l n ( <t r > ) ;
out . p r i n t l n ( <td> ) ;
out . p r i n t l n ( f . f o r m a t ( x [ i ] ) ) ;
out . p r i n t l n ( </td> ) ;
i f ( c >0){
f o r ( i n t j =0; j <c ; j ++){
out . p r i n t l n ( <td> ) ;
out . p r i n t l n ( f . f o r m a t ( k [ i ] [ j ] ) ) ;
out . p r i n t l n ( </td> ) ;
}
}
out . p r i n t l n ( </t r > ) ;
}
out . p r i n t l n ( </ t a b l e > ) ;
}
else {
out . p r i n t l n ( S i s t e m i n c o m p a t i b i l ! ) ;
}
out . p r i n t l n ( </ c e n t e r > ) ;
out . p r i n t l n ( </html></body> ) ;
}
else {
S t r i n g r e z= ;
i f ( dout . g e t E C o m p a t i b i l ( ) ) {
f o r ( i n t i =0; i <l ; i ++){
r e z+=x [ i ] ;
r e z+= ;
i f ( c >0){
f o r ( i n t j =0; j <c ; j ++){
r e z+=k [ i ] [ j ] ;
r e z+= ;
}
}
r e z+= \n ;
}
}
System . out . p r i n t l n ( r e z ) ;
out . p r i n t l n ( r e z . t r i m ( ) ) ;
}

50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

}
catch ( E x c e p t i o n e ) {
System . out . p r i n t l n ( E x c e p t i o n : +e . g e t M e s s a g e ( ) ) ;
}
out . c l o s e ( ) ;

107
108
109
110
111

112
113

CAPITOLUL 9. INCARCAREA
UNUI FIS
IER - UPLOAD

Capitolul 10
Servicii Web
Un serviciu Web este o aplicatie client-server cu serverul gazduit de un server Web,
apelabil prin aplicatia client si realizat potrivit unei interfete de programare specifice.
Protocolul de comunicatie este http.
Sunt cunoscute urmatoarele tipuri de servicii Web:
Servicii bazate pe modelul Remote Precedure Call (RPC) - Apel de Procedura de
la Distanta.
Protocolul de reprezentare a cererii si a raspunsului (de serializare / deserializare)
variaza. Din acest punct de vedere sunt cunoscute:
Servicii xml-rpc (www.xmlrpc.org). Cererea si raspunsul sunt transmise prin
cod xml cuprins n corpul mesajului http.
Servicii json-rpc (www.json-rpc.org) bazat pe reprezentarea JSON.
Servicii hessian. Se utilizeaza un protocol pentru serializare / deserealizare
bazat pe reprezentarea binara a datelor. Protocolul a fost dezvoltat de firma
Caucho Technologies (2007).
Servicii bazate pe interfata de programare Java API for XML Web Services
- JAX-WS. Interfata de programare JAX-WS este varianta cea mai recenta
pentru serviciile cunoscute sub numele de servicii soap-rpc.
Pentru fiecare caz semnalat mai sus sunt realizate implementari n mai multe limbaje
/ platforme de programare.
Servicii REST.
REpresentational State Transfer (REST) este un model de arhitectura de aplicatie
distribuita1 .
REST specifica modul cum o resursa - entitate care contine informatie specifica este definita si cum poate fi adresata.
1

REST a fost introdus de Roy Fielding, n teza sa de doctorat din 2000. Roy Fielding este autorul
principal al specificatiilor protocolului http.

167

168

CAPITOLUL 10. SERVICII WEB

Identificarea unei resurse se face printr-un URI (Universal Resource Identifier ).


Interfata standard de programare a unui serviciu REST este Java API for XML
Restful Services - JAX-WS.
Transferul resursei catre un client si prelucrarea resursei se face prin operatii indicate
de antetele mesajului http GET, POST, PUT, DELETE, etc.
Resursele sunt fara stare iar modelul de aplicatie este cel de client-server.
Pentru sistemelele care satisfac aceste restrictii se utilizeaza terminologia RESTful.
Principalul exemplu de sistem RESTful este World Wide Web (WWW) cu protocolul Hyper Text Transfer Protocol (HTTP).
Serviciile Web bazate pe REST se bazeaza pe accesul la resurse - definite prin
identificatori si nu pe apelarea unor metode, ca n modelul Remote Procedure Call
(RPC).
Standardul JAX-RS Java API for RESTful Web Services a ajuns la versiunea 2.
(Versiunea 1 este definita de JSR 311, iar versiunea 2 este definita de JSR 339)
In prezent, n Java, exista mai multe implementari pentru servicii REST.

10.1

Descrierea unui serviciu

Spre deosebire de aplicatiile bazate pe apelul de procedura la distanta (RMI, CORBA,)


unde prezentarea ofertei se face printr-o interfata Java, ntr-un serviciu JAX-WS, JAX-RS
descrierea sau specificarea acestuia se realizeaza prin sublimbaje xml:
Web Service Description Language - WSDL pentru servicii JAX-WS.
Descrierea datelor din mesajele vehiculate se face prin XML Schema, de asemenea
un sublimbaj xml.
Web Application Description Language - WADL pentru servicii JAX-RS.
Mesajele dintre client si server folosesc protocolul de reprezentare Simple Object Access
Protocol - SOAP care este independent de platforma de calcul si de limbajul de programare. SOAP este tot un sublimbaj xml, standard World Wide Web Consortium - W3C.
In instrumentele actuale de dezvoltare, SOAP este transparent programatorului, dar Java
ofera suport de programare prin pachetul javax.xml.soap.
Produsul soapUI ofera posibilitatea vizualizarii mesajelor SOAP ale serviciilor Web
pornind de la descrierea acestora prin WSDL, respectiv WADL.

10.2

Modelul JAX-WS prin Metro

JSR (Java Specification Request) 109 defineste o interfata de programare (API) pentru
realizarea serviciilor Web bazate pe RPC : Java API for XML Web Services (JAX-WS).
Un asemenea serviciu Web se poate implementa prin:

10.2. MODELUL JAX-WS PRIN METRO

169

servlet:
Serviciul este implementat ca o clasa Java care ruleaza ntr-un container Web, fiind
integrat ntr-un servlet. Integrarea este complet transparenta programatorului.
sesiune EJB (Enterprise Java Bean) fara stare (stateless session):
Serviciul ruleaza ntr-un container EJB.

10.2.1

Serviciu JAX-WS ca servlet

Cadrul de lucru pe care l vom utiliza este Metro, dezvoltat de Oracle. Un scop al
cadrului de lucru Metro este asigurarea interoperabilitatii ntre server si client atunci cand
acestea sunt realizate pe platformele soft Java si .NET, dar faciliteaza si dezvoltarea n
mediul omogen Java. Metro implementeaza modelul JAX-WS.
Alternativ, s-ar fi putut folosi implementarea de referinta jaxws-ri, dezvoltat tot de
Oracle sau apache-CXF.
Metro ofera suport pentru dezvoltarea serviciului Web pe serverele:
apache-tomcat; 2
glassfish.
Instalarea n apache-tomcat se face
prin ant cu fisierul metro-on-tomcat.xml aflat n distributia lui Metro.
fisierele jar aflate n catalogul metro\lib se copiaza n apache-tomcat-*\lib sau n
catalogul WEB-INF\lib al serviciului.
Dezvoltarea aplicatiei server
Clasa serverului este o clasa POJO cu adnotari specifice. Definirea serviciului, a
operatiilor pe care le ofera serviciul si a parametrilor de intrare pentru fiecare operatie se
face utilizand adnotarile @WebService, respectiv @WebMethod si @WebParam.
Vom dezvolta serviciul Web pentru calculul unei integrale. In clasa server se va
crea cate o instanta a claselor mathlib.client.cvadra.JepDataIn si mathlib.client.cvadra.
impl.MetodaSimpsonWeb a mini-bibliotecii mathlib iar rezultatele se obtin apeland metoda
de integrare numerica metodaSimson. In final, sursa devine:
1

package i n t e g r a l a . s e r v e r ;

import
import
import
import
import

4
5
6
7
9
10

j a v a x . j w s . WebMethod ;
j a v a x . j w s . WebParam ;
j a v a x . j w s . WebService ;
mathlib . c l i e n t . cvadra . ;
m a t h l i b . c l i e n t . c v a d r a . impl . MetodaSimpsonWeb ;

@WebService ( )
public c l a s s MetodaSimpsonWS {

Functioneaz
a si n serverul Web jetty.

170

@WebMethod( operationName = i n t e g r e a z a )
public DataOut i n t e g r e a z a (@WebParam( name = a ) S t r i n g a ,
@WebParam( name = b ) S t r i n g b ,
@WebParam( name = s v a r ) S t r i n g s v a r ,
@WebParam( name = e x p r ) S t r i n g expr ,
@WebParam( name = e p s )
S t r i n g eps ,
@WebParam( name = nmi )
S t r i n g nmi ) {

12
13
14
15
16
17
18

JepDataIn d i n=new JepDataIn ( s v a r , e x p r ) ;


d i n . setA ( a ) ;
d i n . setB ( b ) ;
d i n . s e t E p s ( Double . p a r s e D o u b l e ( e p s ) ) ;
d i n . setNmi ( I n t e g e r . p a r s e I n t ( nmi ) ) ;
IMetodaSimpson o b j=new MetodaSimpsonWeb ( ) ;
DataOut dout=o b j . metodaSimpson ( d i n ) ;
return dout ;

20
21
22
23
24
25
26
27

28
29

CAPITOLUL 10. SERVICII WEB

Vom considera structura


myapp
|--> src
|
|--> mypackage
|
|
|--> server
|
|
|
| *.java
|--> war
|
|--> WEB-INF
|
|
|--> classes
|
|
|--> lib
|
|
|
web.xml
|
|
|
sun-jaxws.xml

Compilarea se face prin intermediul utilitarului apt - Annotation Proccessing Tool


din jdk prin intermediul unei sarcini date de clasa com.sun.tools.ws.ant.Apt din Metro.
Codul corespunzator din build.xml este
<taskdef name="apt" classname="com.sun.tools.ws.ant.Apt">
<classpath refid="myclasspath"/>
</taskdef>
<target name="build-server" depends="init">
<apt
fork="true"
debug="true"
destdir="war/WEB-INF/classes"
sourcedestdir="war/WEB-INF/classes"
sourcepath="src">
<classpath>
<path refid="myclasspath"/>
</classpath>
<source dir="src">
<include name="**/server/*.java"/>
</source>
</apt>
</target>

Pe baza claselor din source=src\mypackage\server se vor genera n sourcedestdir


o serie de clase iar rezultatul compilarii se depun n catalogul indicat de destdir.
In cazul exemplului considerat aceste clase sunt integrala.server.jaxws.Integreaza.java
si integrala.server.jaxws.IntegreazaResponse.java.
Sunt necesare fisierele:

10.2. MODELUL JAX-WS PRIN METRO

171

sun-jaxws.xml
1
2
3
4
5
6
7

<?xml version= 1 . 0 e n c o d i n g=UTF8 ?>


<e n d p o i n t s xmlns= h t t p : // j a v a . sun . com/xml/ ns / jax ws/ r i / r u n t i m e version= 2 . 0 >
<e n d p o i n t
name= jaxwsi n t e g r a l a
i m p l e m e n t a t i o n= i n t e g r a l a . s e r v e r . MetodaSimpsonWS
u r l p a t t e r n= / i n t e g r a l a />
</ e n d p o i n t s>

web.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

<?xml version= 1 . 0 e n c o d i n g=UTF8 ?>


<webapp version= 2 . 4 xmlns= h t t p : // j a v a . sun . com/xml/ ns / j 2 e e
x m l n s : x s i= h t t p : //www. w3 . o r g /2001/XMLSchemai n s t a n c e
x s i : s c h e m a L o c a t i o n= h t t p : // j a v a . sun . com/xml/ ns / j 2 e e
h t t p : // j a v a . sun . com/xml/ ns / j 2 e e /weba p p 2 4 . xsd >
< l i s t e n e r>
< l i s t e n e r c l a s s>
com . sun . xml . ws . t r a n s p o r t . h t t p . s e r v l e t . W S S e r v l e t C o n t e x t L i s t e n e r
</ l i s t e n e r c l a s s>
</ l i s t e n e r>
< s e r v l e t>
<s e r v l e t name> i n t e g r a l a</ s e r v l e t name>
<s e r v l e t c l a s s>com . sun . xml . ws . t r a n s p o r t . h t t p . s e r v l e t . WSServlet</ s e r v l e t c l a s s>
<l o a d ons t a r t u p>1</ l o a d ons t a r t u p>
</ s e r v l e t>
<s e r v l e t mapping>
<s e r v l e t name> i n t e g r a l a</ s e r v l e t name>
<u r l p a t t e r n>/ i n t e g r a l a</ u r l p a t t e r n>
</ s e r v l e t mapping>
<s e s s i o n c o n f i g>
<s e s s i o n t i m e o u t>60</ s e s s i o n t i m e o u t>
</ s e s s i o n c o n f i g>
</webapp>

Se retin urmatoarele corelatii ale denumirilor:


url-pattern fixat n web.xml este redeclarat n fisierele sun-jaxws.xml.
Numele serviciului declarat n sun-jaxws.xml trebuie sa fie numele arhivei war.
Pentru exemplul nostru, wsdl -ul serviciului va fi disponibil la
http://localhost:8080/jaxws-integrala/integrala?wsdl

Dezvoltarea aplicatiei client. Realizarea aplicatiei client presupune ca serviciul sa


fie activ pe serverul Web.
Dezvoltarea partii (aplicatiei) client ncepe cu generarea unor clase care mijlocesc
apelarea serviciului. Generarea se face utilizand utilitarul wsimport din jdk pe baza
accesarii fisierului wsdl asociat serviciului.
Codul obiectivului din build.xml este
<target name="generate-client" depends="init">
<exec executable="${env.JAVA_HOME}/bin/wsimport">
<arg value="-d"/>
<arg value="${build.dir}"/>

172

CAPITOLUL 10. SERVICII WEB

<arg
<arg
<arg
<arg
</exec>
</target>

value="-keep"/>
value="-p"/>
value="${app.name}.client"/>
value="${wsdl.uri}"/>

Optiunea -d specifica locatia unde se depun fisierele generate, optiunea -p indica pachetul
din care fac parte clasele generate.
Dintre aceste clase, n codul clientului propriu-zis se foloseste clasa MetodaSimpsonWSService. Numele clasei s-a obtinut adaugand sufixul Service la numele clasei server.
Aceasta clasa contine metoda getMetodaSimpsonWSPort() ce returneaza un reprezentant
al serviciului pe calculatorul clientului.
Astfel referinta la serviciu se obtine prin
MetodaSimpsonWSService service=new MetodaSimpsonWSService();
MetodaSimpsonWS port=service.getMetodaSimpsonWSPort();
Prin variabila port putem apela orice operatie a serviciului.
Codul clientului este
1
2
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

package i n t e g r a l a . c l i e n t ;
import j a v a . u t i l . S c a n n e r ;
public c l a s s C l i e n t I n t e g r a l a {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
MetodaSimpsonWSService s e r v i c e=new MetodaSimpsonWSService ( ) ;
MetodaSimpsonWS p o r t=s e r v i c e . getMetodaSimpsonWSPort ( ) ;
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
System . out . p r i n t l n ( E x t r e m i t a t e a s t a n g a ) ;
S t r i n g a=s c a n n e r . n e x t ( ) ;
System . out . p r i n t l n ( E x t r e m i t a t e a d r e a p t a ) ;
S t r i n g b=s c a n n e r . n e x t ( ) ;
System . out . p r i n t l n ( S i m b o l u l v a r i a b i l e i ) ;
S t r i n g s v a r=s c a n n e r . n e x t ( ) ;
System . out . p r i n t l n ( E x p r e s i a de i n t e g r a t ) ;
S t r i n g e x p r=s c a n n e r . n e x t ( ) ;
System . out . p r i n t l n ( T o l e r a n t a ) ;
S t r i n g e p s=s c a n n e r . n e x t ( ) ;
System . out . p r i n t l n ( Numar maxim admis de i t e r a t i i ) ;
S t r i n g nmi=s c a n n e r . n e x t ( ) ;
DataOut dout=p o r t . i n t e g r e a z a ( a , b , s v a r , expr , eps , nmi ) ;
System . out . p r i n t l n ( I n d i c a t o r u l de r a s p u n s : +dout . g e t I n d ( ) ) ;
System . out . p r i n t l n ( I n t e g r a l a : +dout . g e t I n t e g r a l a ( ) ) ;
System . out . p r i n t l n ( Numar de i t e r a t i i e f e c t u a t e : +dout . g e t N i ( ) ) ;
}
}

Instructiunea port.integreaza(. . . ) este blocanta, fapt pentru care aceasta varianta de


program client este denumita sincrona. Interfata de programare JAX-WS permite construirea de clienti asincroni, caz n care apelarea unei operatii returneaza obiecte de tip
java.util.concurrent.Future si este neblocanta.

10.3

Modelul JAX-RS prin jersey

Entitatile utilizate sunt:

10.3. MODELUL JAX-RS PRIN JERSEY

173

Clasa resursa - Resource class. Resursa Web este reprezinta de o clasa Java cu
adnotari JAX-RS. Clasa resursa radacina - Root resource class. Clasa cu adnotarea
@Path. Resursele adiacente se definesc relativ la aceasta clasa (resursa).
Metoda de identificare a cererii - Request method designator. Adnotarea @GET /
@POST /@PUT / @DELETE este folosita pentru identificarea cererii HTTP n vederea
desemnarii metodei de generare / prelucrare a resursei.
Metoda de generare / prelucrare a resusei - Resource method.
Localizator a resurselor adiacente - Sub-resource locator. Metoda pentru localizarea
a resurselor adiacente, adica a resurselor care se specifica relativ la resursa radacina.
Metoda de generare / prelucrare a unei resurse adiacente - Sub-resource method.
Provider o implementare a interfetei JAX-RS.
O implementare de referinta (Reference Implementation - RI) este oferita de pachetul
jersey-*.*.* realizat de Oracle.
Serverul Web care se va utiliza va fi apache-tomcat. In vederea desfasurarii, serviciul se
arhiveaza, avand extensia war. Numele arhivei va desemna numele serviciului. Structura
care se arhiveaza va fi
catalogul_serviciului_RESTful
|--> WEB-INF
|
|--> classes
|
|
|--> resources
|
|
|
|
*.class
|
|--> lib
|
|
|
*.jar
|
index.html sau index.jsp
Printre fisierele *.class se gasesc resursele serviciului. Fisierele *.jar sunt cele din catalogul
lib al distributiei jersey si eventual cele cerute de aplicatie. index.html sau index.jsp ofera
oportunitatea apelarii serviciului si de obicei reprezinta un client Web.
Serviciul RESTful este oferit prin intermediul unui servlet
org.glassfish.jersey.servlet.ServletContainer,
complet transparent programatorului, specificat doar n fisierul web.xml :
1
2
3
4
5
6
7
8
9
10
11

<?xml version= 1 . 0 e n c o d i n g=UTF8 ?>


< ! This web . xml f i l e i s n o t r e q u i r e d when u s i n g S e r v l e t 3 . 0 c o n t a i n e r ,
see implementation d e t a i l s
h t t p : // j e r s e y . j a v a . n e t / nonav / d o c u m e n t a t i o n / l a t e s t / j a x r s . html >
<webapp version= 2 . 5 xmlns= h t t p : // j a v a . sun . com/xml/ ns / j a v a e e
x m l n s : x s i= h t t p : //www. w3 . o r g /2001/XMLSchemai n s t a n c e
x s i : s c h e m a L o c a t i o n= h t t p : // j a v a . sun . com/xml/ ns / j a v a e e
h t t p : // j a v a . sun . com/xml/ ns / j a v a e e /weba p p 2 5 . xsd >
< s e r v l e t>
<s e r v l e t name>J e r s e y Web A p p l i c a t i o n</ s e r v l e t name>
<s e r v l e t c l a s s>o r g . g l a s s f i s h . j e r s e y . s e r v l e t . S e r v l e t C o n t a i n e r</ s e r v l e t c l a s s>

174

12
13
14
15
16
17
18
19
20
21
22

CAPITOLUL 10. SERVICII WEB

<i n i t param>
<paramname> j e r s e y . c o n f i g . s e r v e r . p r o v i d e r . p a c k a g e s</paramname>
<paramv a l u e>r e s o u r c e s</paramv a l u e>
</ i n i t param>
<l o a d ons t a r t u p>1</ l o a d ons t a r t u p>
</ s e r v l e t>
<s e r v l e t mapping>
<s e r v l e t name>J e r s e y Web A p p l i c a t i o n</ s e r v l e t name>
<u r l p a t t e r n>/ r e s o u r c e s /</ u r l p a t t e r n>
</ s e r v l e t mapping>
</webapp>

Toate resursele trebuie sa faca parte din n catalogul resources.


Problema de programare constau n:
declararea unei resurse
adnotarea @Path(uriResursa) defineste o resursa;
adnotarile @GET, @POST, etc indica metoda care solicita resursa;
adnotarea @Produces(String MIME-type) indica tipul resursei;
preluarea parametrilor pentru care exista mai multe variante de programare:
prin context, indicat de adnotarea @Context;
prin adnotarea @QueryParam pentru metada get sau adnotarea @FormParam n
cazul utilizarii metodei post;
prin adnotarea @PathParam;
prin componente java, datele sunt cuprinse ntr-o componenta Java (o clasa
POJO - Plain Old Java Object) care este convertita n mesaj XML sau JSON.
Exista mai multe implementari ale acestei tehnologii care solicita resurse suplimentare distributiei jersey (MoXy POJO, jackson).
generarea resursei se obtine prin intermediul claselor:
javax.ws.rs.core.Response
Metoda public static Response.ResponseBuilder ok(Object method,
String MIME-type) genereaza resursa prin intermediul metodei method.
javax.ws.rs.core.Response.ResponseBuilder
Metoda public abstract Response build() va returna obiectul Response
n urma executarii metodei ok.
Semnalam posibilitatea programarii asincrone a generarii resursei.
Exemplificam din nou cu calculul unei integrale utilizand resursele mini-bibliotecii
mathlib. Serviciul va putea returna rezultatul sub forma de text/plain sau text/html.
Codul serviciului este:

10.3. MODELUL JAX-RS PRIN JERSEY

1
2
3
4
5
6
7
8
9

package r e s o u r c e s ;
im po rt j a v a x . ws . r s . QueryParam ;
im po rt j a v a x . ws . r s . c o r e . Response ;
im po rt j a v a x . ws . r s . Path ;
im po rt j a v a x . ws . r s .GET;
im po rt m a t h l i b . c l i e n t . c v a d r a . JepDataIn ;
im po rt m a t h l i b . c l i e n t . c v a d r a . DataOut ;
im po rt m a t h l i b . c l i e n t . c v a d r a . IMetodaSimpson ;
im po rt m a t h l i b . c l i e n t . c v a d r a . impl . MetodaSimpsonWeb ;

14

@Path ( i n t e g )
public c l a s s IntegResource {
p r i v a t e DataOut dout ;
p r i v a t e d o u b l e s=Double . NaN ;

16

p u b l i c I n t e g R e s o u r c e ( ) {}

11
12
13

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

@GET
p u b l i c Response doGet (
@QueryParam ( s v a r ) S t r i n g s v a r ,
@QueryParam ( e x p r ) S t r i n g expr ,
@QueryParam ( a ) S t r i n g a ,
@QueryParam ( b ) S t r i n g b ,
@QueryParam ( nmi ) S t r i n g nmi ,
@QueryParam ( e p s ) S t r i n g eps ,
@QueryParam ( t i p ) S t r i n g t i p ) {
JepDataIn d i n=new JepDataIn ( s v a r , e x p r ) ;
d i n . setA ( a ) ;
d i n . setB ( b ) ;
d i n . s e t E p s ( Double . p a r s e D o u b l e ( e p s ) ) ;
d i n . setNmi ( I n t e g e r . p a r s e I n t ( nmi ) ) ;
IMetodaSimpson o b j=new MetodaSimpsonWeb ( ) ;
dout=o b j . metodaSimpson ( d i n ) ;
i n t n t i p =0;
i f ( t i p . e q u a l s ( t e x t / html ) ) n t i p =1;
Response r=n u l l ;
switch ( ntip ){
case 0 :
r=Response . ok ( g e t P l a i n R e p ( ) , t e x t / p l a i n ) . b u i l d ( ) ;
break ;
case 1 :
r=Response . ok ( getHtmlRep ( ) , t e x t / html ) . b u i l d ( ) ;
break ;
}
return r ;

35
36
37
38
39
40
41
42
43
44
45
46
47

49

p ub l ic S tr in g getPlainRep ( ) {
S t r i n g r e z u l t a t= ;
r e z u l t a t=r e z u l t a t+
I n d i c a t o r u l de r a s p u n s : + ( new I n t e g e r ( dout . g e t I n d ( ) ) ) . t o S t r i n g ()+ \n ;
r e z u l t a t=r e z u l t a t+
I n t e g r a l a : + ( new Double ( dout . g e t I n t e g r a l a ( ) ) ) . t o S t r i n g ()+ \n ;
r e z u l t a t=r e z u l t a t+
Numar de i t e r a t i i e f e c t u a t e : + ( new I n t e g e r ( dout . g e t N i ( ) ) ) . t o S t r i n g ( ) ;
return rezultat ;
}

50
51
52
53
54
55
56
57
58
60
61
62
63
64
65
66

p u b l i c S t r i n g getHtmlRep ( ) {
S t r i n g r e z u l t a t=<html><head></head><body b g c o l o r=
\ #bbeebb \ ><c e n t e r ><h1>R e z u l t a t u l f u r n i z a t de s e r v i c i u l RESTfull ;
r e z u l t a t=r e z u l t a t+<t a b l e b o r d e r=\ 1\ > ;
r e z u l t a t=r e z u l t a t+<t r > ;
r e z u l t a t=r e z u l t a t+<td> I n d i c a t o r u l de r a s p u n s </td> ;
r e z u l t a t=r e z u l t a t+<td>+(new I n t e g e r ( dout . g e t I n d ( ) ) ) . t o S t r i n g ()+ </td> ;

175

176

r e z u l t a t=r e z u l t a t+</t r > ;


r e z u l t a t=r e z u l t a t+<t r > ;
r e z u l t a t=r e z u l t a t+<td> I n t e g r a l a </td> ;
r e z u l t a t=r e z u l t a t+<td>+(new Double ( dout . g e t I n t e g r a l a ( ) ) ) . t o S t r i n g ()+ </td> ;
r e z u l t a t=r e z u l t a t+</t r > ;
r e z u l t a t=r e z u l t a t+<t r > ;
r e z u l t a t=r e z u l t a t+<td> Numarul i t e r a t i i l o r e f e c t u a t e </td> ;
r e z u l t a t=r e z u l t a t+<td>+(new I n t e g e r ( dout . g e t N i ( ) ) ) . t o S t r i n g ()+ </td> ;
r e z u l t a t=r e z u l t a t+</t r > ;
r e z u l t a t=r e z u l t a t+</ t a b l e ></h1></c e n t e r ></body></html> ;
return rezultat ;

67
68
69
70
71
72
73
74
75
76
77

78
79

CAPITOLUL 10. SERVICII WEB

Apelarea serviciului RESTful dintr-un navigator (clientul Web) se obtine cu


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

<html>
<body bgcolor=#bbeebb >
<center>
<h1> C a l c u l u l u n e i i n t e g r a l e p r i n t r un s e r v i c i u RESTful </h1>
<form method= g e t
action= / i n t e g r a l a / r e s o u r c e s / i n t e g >
<p>I n t r o d u c e &#355; i</p>
<table border= 1 >
<tr>
<td> S i m b o l u l v a r i a b i l e i </td>
<td> <input type= t e x t name= s v a r s i z e= 10 />
</ tr>
<tr>
<td> E x p r e s i a f u n c &#355; i e i de i n t e g r a t </td>
<td> <input type= t e x t name= e x p r s i z e= 10 />
</ tr>
<tr>
<td> E x t r e m i t a t e a s t &#226;g&#259; </td>
<td> <input type= t e x t name= a s i z e= 10 />
</ tr>
<tr>
<td> E x t r e m i t a t e a d r e a p t &#259; </td>
<td> <input type= t e x t name=b s i z e= 10 />
</ tr>
<tr>
<td> Num&#259; r u l maxim admis de i t e r a &#355; i i </td>
<td> <input type= t e x t name=nmi s i z e= 10 value= 50 />
</ tr>
<tr>
<td> T o l e r a n &#355;a </td>
<td> <input type= t e x t name= e p s s i z e= 10 value= 1 e6 />
</ tr>
<tr>
<td> S e l e c t a &#355; i t i p u l r &#259; s p u n s u l u i </td>
<td>
<s e l e c t name= t i p >
<option value= t e x t / p l a i n > Text / P l a i n </ option>
<option value= t e x t / html > Text /Html </ option>
</ s e l e c t>
</td>
</ tr>
<tr a l i g n= c e n t e r >
<td> <input type= submit value= C a l c u l e a z a /> </td>
</ tr>
</ table>
</form>
</ center>
</body>
</html>

10.3. MODELUL JAX-RS PRIN JERSEY

177

Produsul jersey ofera o modalitate simpla de programare a unui client pentru un


serviciu RESTful:
1
2
3
4
5
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

package i n t e g ;
import j a v a x . ws .
import j a v a x . ws .
import j a v a x . ws .
import j a v a . u t i l

rs . c l i en t . Client ;
rs . client . ClientBuilder ;
r s . c l i e n t . WebTarget ;
. Scanner ;

public c l a s s J e r s e y C l i e n t {
public s t a t i c void main ( S t r i n g a r g s [ ] ) {
C l i e n t c l i e n t = C l i e n t B u i l d e r . newClient ( ) ;
S t r i n g rootURL= h t t p : / / l o c a l h o s t : 8 0 8 0 / i n t e g r a l a / r e s o u r c e s / i n t e g ;
WebTarget webTarget = c l i e n t . t a r g e t ( rootURL ) ;
S c a n n e r s c a n n e r=new S c a n n e r ( System . i n ) ;
System . out . p r i n t l n ( E x t r e m i t a t e a s t a n g a ) ;
S t r i n g a=s c a n n e r . n e x t ( ) ;
System . out . p r i n t l n ( E x t r e m i t a t e a d r e a p t a ) ;
S t r i n g b=s c a n n e r . n e x t ( ) ;
System . out . p r i n t l n ( S i m b o l u l v a r i a b i l e i ) ;
S t r i n g s v a r=s c a n n e r . n e x t ( ) ;
System . out . p r i n t l n ( E x p r e s i a de i n t e g r a t ) ;
S t r i n g e x p r=s c a n n e r . n e x t ( ) ;
System . out . p r i n t l n ( T o l e r a n t a ) ;
S t r i n g e p s=s c a n n e r . n e x t ( ) ;
System . out . p r i n t l n ( Numar maxim admis de i t e r a t i i ) ;
S t r i n g nmi=s c a n n e r . n e x t ( ) ;
S t r i n g r e s p o n s e=webTarget .
queryParam ( s v a r , s v a r ) .
queryParam ( e x p r , e x p r ) .
queryParam ( a , a ) .
queryParam ( b , b ) .
queryParam ( nmi , nmi ) .
queryParam ( e p s , e p s ) .
queryParam ( t i p , t e x t / p l a i n ) .
request ( ) . get ( String . class ) ;
System . out . p r i n t l n ( r e s p o n s e ) ;
}
}

178

CAPITOLUL 10. SERVICII WEB

Partea II
Programare paralel
a n Java

179

Capitolul 11
Introducere n programarea
concurent
a / paralel
a
11.1

Procese paralele

Evenimentele se petrec n spatiu si timp. Exista urmatoarele posibilitati: doua evenimente se petrec n acelasi loc la alte momente de timp (succesiv, secvential) sau cele
doua evenimente se petrec n acelasi timp, dar n locuri diferite (concomitent, concurent,
paralel). Astfel paralelismul este o trasatura a acestui univers.
Apare astfel naturala cerinta ca un calculator sa poata simula sau exe- cuta operatii,
activitati paralele.
In cele ce urmeaza printr-un proces se va ntelege un sir de actiuni executate cate una
singura la un moment dat, iar un procesor va indica un dispozitiv care executa instructiuni
n mod secvential.
A
O.C., POPESCU
Mai precis un proces este caracterizat de urmatoarele atribute (BASC
I., 1989):
indivizibilitatea: Procesul este o unitate atomica care nu mai este divizat n alte
unitati carora sistemul de calcul sa le aloce resurse n mod autonom.
secventialitatea: Operatiile unui proces se executa cate una singura la un moment
dat.
asincronismul: Un proces se desfasoara independent de celelalte procese, cu exceptia
momentelor de interactiune cu alte procese.
temporalitatea: Un proces exista, se manifesta si este recunoscut numai n intervalul
de timp dintre lansarea sa n executie si terminarea sa.
Intr-un program, un proces are o existenta formata din mai multe stari:
Trecerea de la starea inexistent la starea creat se face prin declararea procesului.
Din starea creat un proces ajunge n starea executabil prin lansarea n executie sau
printr-o forma de activare. Starea executabil are doua substari:
181

182

CAPITOLUL 11. INTRODUCERE IN PROGRAMAREA CONCURENTA

1. starea gata de executare: procesul este pregatit pentru executare, dar nu i s-a
alocat nca un procesor logic/fizic;
2. starea n curs de executare: procesului i s-a alocat un procesor logic/fizic care
i executa instructiunile.
La terminarea executarii unui proces, acesta trece n starea terminat.
In final procesele sunt distruse - automat sau prin instructiuni - trecandu-se n starea
inexistent.
Un proces se poate bloca, mai precis poate fi
amanat : ntreruperea pentru un anumit timp a executiei procesului.
suspendat : ntreruperea executiei pe baza unei relatii cu alte procese. Procesul
poate reveni ulterior n starea de executabil, reluand executarea instructiunilor din
momentul suspendarii. Trecerea n starea executabil se realizeaza fie aleator, fie cu
disciplina unei cozi.
Un calculator cu procesare paralela poate fi definit, ntr-o prima aproximatie, ca o
masina capabila sa execute diferite operatii utilizand simultan cel putin doua procesoare.
Merita de semnalat aici clasificarea lui Flynn: Din punctul de vedere al secventei
de instructiuni executate de catre un sistem de calcul si al secventei de date asupra careia
actioneaza instructiunile la un moment dat, se pun n evidenta urmatoarele modele de
calculatoare:
SISD : Single Instruction, Single Data stream;
SIMD : Single Instruction, Multiple Data stream;
MIMD : Multiple Instruction, Multiple Data stream.
Modelul SISD corespunde sistemelor de calcul obisnuite, iar modelele SIMD si MIMD
caracterizeaza sistemele de calcul ce ofera facilitati de calcul paralel. In modelul SIMD
toate procesoarele efectueaza aceleasi operatii dar pe multimi de date diferite, n timp
ce n modelul MIMD procesoarele efectueaza secvente distincte de operatii asupra unor
multimi de date.
Daca executia proceselor se efectueaza concomitent pe procesoare diferite atunci executia
se numeste paralela.
Daca executia proceselor se efectueaza cu un singur procesor atunci executia se numeste
concurenta.
Pretul de achizitie, ntretinere si exploatare al unui calculator paralel fiind mare, pentru orice institutie problema achizitionarii unui asemenea calculator se pune n termenii
raportului eficienta/cost. Necesitatea de a dispune de o putere de calcul cat mai mare
la preturi cat mai mici a condus la solutii care permit programare paralela ntr-o retea
obisnuita de calculatoare.
In cazul n care procesele se executa pe calculatoare distincte, legate ntr-o retea,
atunci executia se numeste distribuita, paralel - distribuita.

11.1. PROCESE PARALELE

183

Un grup de calculatoare interconectate avand un singur punct de administrare si ale


caror resurse sunt unite pentru rezolvarea unei probleme formeaza un cluster.
Un grup de calculatoare interconectate, fiecare cu posibilitatea de administrare proprie
care si reunesc resursele pentru la rezolvarea unei probleme formeaza un grid.
De multe ori diferenta dintre cluster si grid este mai mult de natura politicii de utilizare
decat de natura tehnica.
Daca calculatoarele apartin unui intranet se mai utilizeaza terminologia de retea de
statii de lucru (network of workstations), iar daca calculatoarele sunt conectate prin internet atunci se utilizeaza termenul de grid.
O memorie partajabila se va considera ca este de tip PRAM (Parallel Random Access
Memory). Modelul PRAM presupune ca toate procesele au acces la respectiva memorie
comuna, fiecare proces comunica n ambele sensuri cu memoria partajabila n sensul ca
poate scrie si citi date n locatiile memoriei.
Reglementarea accesului la memoria comuna se face conform disciplinei CREW (Concurrent Read; Exclusive Write). Potrivit acestei restrictii, este permisa citirea n paralel
(concomitent) din aceasi locatie de memorie de catre doua sau mai multe procese, dar
scrierea concomitenta n aceasi locatie este interzisa.
Programarea paralela si paralel-distribuita apare ca o combinatie a doua tipuri de
activitati:
de calcul, specific aplicatiei, executata de procese;
de coordonare, responsabila de efectuarea comunicatiilor si de lansare a proceselor.
Exista mai multe ncercari de definire a coordonarii (PAPADOPOULOS G.A., ARBAB
F., 1998):
coordonarea consta n gestionarea dependintelor dintre activitati;
coordonarea este procesul de construire a programelor prin lipirea proceselor.
Un model de coordonare este liantul prin care sunt lipite activitatile separate (procesele) ntr-un ansamblu.
Din punctul de vedere al programarii, modelele de coordonare apartin uneia din categoriile:
Coordonare condusa prin date (data-driven) evolutia n orice moment se decide n
functie de datele de expediat sau de cele receptionate. Coordonatorul este responsabil de examinarea si manipularea datelor necesare coordonarii proceselor.
In acesta categorie intra aplicatiile bazate pe o memorie comuna, partajata.
Coordonarea condusa prin sarcini sau orientata pe procese (control driven / task
driven / process oriented ). In acest caz lansarea proceselor este independenta de
date. Aplicatiile bazate pe Communicating Sequential Processes (CSP) - dezvoltat
de C.A.R. Hoare apartin acestei categorii: JCSP.

184

CAPITOLUL 11. INTRODUCERE IN PROGRAMAREA CONCURENTA

11.2

Probleme specifice calculului paralel

Pentru a ntelege problemele care se ridica la realizarea unui program n care exista
procese ce se executa n paralel consideram doua exemple deosebit de importante.
1. Se considera un sistem de rezervare de bilete n care de la doua terminale se poate
cere ocuparea unor locuri. Actiunile necesare rezervarii sunt executate de procesele
P1 si P2 care se desfasoara n paralel; permitand solicitarea de bilete n orice moment,
de la oricare terminal. Fiecare operatiune de rezervare impune, printre altele, si
incrementarea unei variabile v, care indica numarul total de locuri ocupate.
2. Fie un sistem format din doua procese P1 si P2 , primul producand niste date care
apoi vor fi preluate de cel de al doilea. Comunicarea ntre cele doua procese se realizeaza prin intermediul unei zone de memorie tampon, de o anumita dimensiune,
n care procesul P1 introduce informatii (sub forma unor nregistrari), pe care apoi
P2 le extrage.
Procesul P2 nu este nevoit sa astepte pentru fiecare nregistrare n parte, iar P1
nu astepta pana ce P2 este gata sa receptioneze nregistrarea produsa. Procesele
evolueaza independent unul de cela- lalt, P1 introducand n tampon nregistrarea
produsa, de unde P2 o va extrage la nevoie.
Se impun urmatoarele restrictii:
Procesul P1 ncearca sa introduca o nregistrare n tampon si constata ca acesta
s-a umplut. In acest caz, el va trebui sa astepte pana ce se iveste un loc n
tampon (ceea ce se va ntampla ca urmare a extrageri unei nregistrari de catre
P2 ).
Procesul P2 ncearca sa extraga o nregistrare si constata ca tamponul este gol.
In acest caz el va trebui sa astepte pana ce apare o nregistrare ca urmare a
introduceri unei nregistrari n tampon de catre P1 .
Din aceste exemple se deduce ca ntre procese exista interactiuni de forma:
comunic
ari: transmitere de informatii ntre procese;
sincroniz
ari: restrictii asupra evolutiei n timp a unui proces.
Problemele de sincronizare sunt:
1. Excluderea reciproc
a ( mutual
a ) : Forma de sincronizare prin care se evita
utilizarea simultana de catre mai multe procese a unei resurse critice. O resursa
este critica daca, la un moment dat, poate fi utilizata doar ntr-un proces.
Variabila v din Exemplul 1 este o resursa critica. Procesele P1 si P2 nu pot accesa
simultan aceasta variabila, altfel spus, cele doua procese trebuie sa se sincronizeze
prin excludere reciproca.

11.2. PROBLEME SPECIFICE CALCULULUI PARALEL

185

2. Sincronizarea pe conditie : Forma de sincronizare prin care se amana executarea sau continuarea executarii unui proces pana cand o anumita conditie devine
adevarata.
Procesele P1 si P2 ale Exemplului 2 trebuie sa se sincronizeze n cazul n care tamponul este plin, respectiv gol.
Un caz particular al sincronizarii pe conditie este sincronizarea barier
a. Mai multe
procese executa aceasi prelucrare, ntre care exista un marcaj - care reprezinta bariera.
Un proces ce ajunge la marcaj se blocheaza pana n momentul n care toate procesele
ating marcajul, dupa care se deblocheaza si si continua executia.
Sistemul de programare paralela / concurenta reprezinta o interfata (software si/sau
hardware) ntre program si sistemul de calcul, el furnizand printre altele, primitive pentru comunicare ntre procese si pentru sincronizarea lor. Primitivele de sincronizare sunt
operatiile pe care sistemul de programare paralela / concurenta le pune la dispozitia programatorului n vederea rezolvarii problemelor de sincronizare. Practic, aceste primitive
se prezinta programatorului sub forma unor instructiuni oarecare, pe care programatorul
le poate folosi fara a cunoaste modul lor de implementare.
Rezultatele unui program executat de un sistem de calcul n care exista procese paralele
trebuie sa fie independent de vitezele relative de executie ale proceselor si de ordinea n
care acestea sunt executate, atunci cand nu sunt supuse unor restrictii de precedenta.
Modelul de aplicatie utilizat n cele mai multe cazuri este cel de dispecer - lucrator
(master - slave). O componenta a aplicatiei - dispecerul - coordoneaza si distribuie o
serie de activitati de calcul lucratorilor. Dupa efectuarea calculelor, lucratorii transmit
rezultatele dispecerului, care le utilizeaza pentru finalizarea rezolvarii problemei.
Acest model de aplicatie este opusul modelului client - server, n care clientii solicita
serverului efectuarea unor prelucrari. De data asta, aplicatia server este cel care efectueaza
operatiile de prelucrare.
S-au pus n evidenta o serie de modele (tipuri) de programe / aplicatii specifice calculului paralel:
Program SPMD (Single Program, Multiple Data) un program actioneaza simultan,
prin acelasi cod, asupra datelor n procese distincte.
Modelul nodal o instanta a aceluiasi program este executat de fiecare proces.
In vederea executarii unei aplicatii paralel - distribuita ntr-o retea de statii de lucru
trebuie efectuate operatiile:
definirea retelei de statii de lucru prin instalarea si lansarea n executie a suportului
soft utilizat;
desfasurarea aplicatiei (deployment), adica instalarea aplicatiei mpre- una cu resurselor
necesare pe fiecare calculator al retelei;
lansarea n executie a aplicatiei - a lucratorilor si a dispecerului.

186

11.3

CAPITOLUL 11. INTRODUCERE IN PROGRAMAREA CONCURENTA

Eficienta programelor paralele

Atribute de calitate ale programelor. In multe domenii concurenta devine cerinta


majora a algoritmilor si programelor. De aici si importanta scalabilitatii unui program,
adica proprietatea/atributul sau de a se adapta eficient la cresterea numarului de procesoare. Un program care foloseste numai un numar fixat de procesoare nu este un program
performant, la fel ca un program care poate rula doar pe un tip de calculatoare aspect
ce vizeaza portabilitatea.
Scalabilitatea si portabilitatea sunt atribute importante ale unui produs informatic.
Intr-un sistem multiprocesor sau distribuit, n cadrul unui proces costul/timpul de
acces la memoria propriului procesor - read/write - este mai mic decat la memoria altui
procesor, realizat prin transmisii de mesaje - send/receive -. In acest fel punem n evidenta
proprietatea localizarii, de a pastra un raport convenabil ntre cele doua feluri de acces la
resurse.
Alaturi de concurenta, scalabilitate, localizare, o alta trasatura a programelor paralele este modularitatea. Pentru stapanirea si gestionarea fenomenelor legate de executia,
comunicatii, sincronizari, etc. programele se alcatuiesc din procese (module).
Daca rezolvarea unei probleme utilizeaza p procese, iar executia procesului i are loc n
ti unitati de timp, i {1, 2, . . . , p} atunci vorbim de ncarcare echilibrata a procesoarelor
daca
tmediu
1,
=
max1ip ti
P
unde tmediu = p1 pi=1 ti . Numarul se numeste indice de ncarcare a proceselor.
Indice de performant
a. Evaluarea performantelor unui program se poate face prin
indicele de performanta, definit ca numarul de operatii n virgula mobila efectuate n
unitatea de timp. Indicele de performanta se exprima n Flops: 1 Flops=1 operatie / 1
s; 106 Flops= 1 MFlops; 109 Flops=1 GFlops= 1 Cray.
Exemplul 11.3.1
Fie sirul (ai )iN si P un program care calculeaza suma
Sn =

n
X

ai

i=1

n tn secunde.
Pentru calculul lui Sn sunt necesare n 1 adunari, astfel indicele de performanta este
n1
.
tn
In analiza indicelui de performanta, prezinta interes determinarea valorii lui nc de la
care tn 1 si n plus tn variaza proportional cu n.
In Java masurarea timpului face apel la metoda clasei System
static long currentTimeMillis()

11.3. EFICIENT
A PROGRAMELOR PARALELE

187

care returneaza numarul de milisecunde de la data de 1 ianuarie 1970.


Subliniem principiul de incertitudine a calculatorului: nu se poate masura timpul
de calcul al unui program cu precizie oricat de mica folosind chiar calculatorul pentru
efectuarea masuratorii.
Un alt indicator util este raportul lucru / memorie - W M . Se numeste lucru numarul
de operatii n virgula mobila efectuate de un program, iar cantitatea de memorie este dat
de numarul de locatii de memorie necesare programului pentru datele de intrare, pentru
retinerea rezultatelor partiale si a celor finale.
In cazul Exemplului 11.3.1 sunt necesare n + 1 locatii de memorie, deci W M = n1 .
n+1
Exemplul 11.3.2
P
Fie A Mn (R), x, y Rn , y = Ax. Daca yi = ni=1 ai,j xj atunci pentru calculul componentei yi sunt necesare n nmultiri si n 1 adunari. Rezulta W M = n(2n1)
.
n2 +2n
Teorema 11.3.1 Daca ntre unitatea centrala si memorie se pot transfera n unitatea de
timp numere n virgula mobila, atunci indicele de performanta este majorat de W M .
Notand cu w lucrul si cu m cantitatea de memorie utilizata de un program, durata de
executie t este mai mare decat durata transferului ttransf er a celor m date ntre unitatea
centrala si memorie.
m
t ttransf er .

Pentru indicele de performanta rezulta


w
w
= W M .
t
m
Eficienta programelor paralele. Corespunzator rezolvarii unei probleme introducem variabilele:
T0 timpul celui mai performant program/algoritm utilizat pe un sistem uniprocesor;
Tp timpul folosit de programul/algoritmul paralel utilizand un sistem de calcul cu p
procesoare.
Eficienta unui program/algoritm se poate evalua cu indicatorii
1. Sp = TTp0 acceleratia paralela.
Are loc inegalitatea Sp p. Intr-adevar, daca
presupunem prin absurd ca Sp = TTp0 > p pTp < T0 atunci utilizand acel algoritm
si folosind doar un singur procesor am avea T1 < T0 , ceea ce contrazice definitia lui
T0 .
2. Sp = TTp1 viteza algoritmica. Acest indicator scoate n evidenta efectele sincronizarilor
si ale comunicatiilor. Ideal, valoarea acestui indicator ar fi p.
3. Ep =

Sp
p

eficienta n cazul utilizarii a p procesoare.

188

CAPITOLUL 11. INTRODUCERE IN PROGRAMAREA CONCURENTA

S-au formulat diverse evaluari ale vitezei algoritmice care neaga (Amdahl G.M., 1967)
si respectiv valideaza (Gustafson J.L., 1988) oportunitatea construirii calculatoarelor paralele cu numar mare de procesoare.
Urmand prezentarea lui Shi Y. (Reevaluating Amdahls Law and Gustafsons Law,
http://cgvr.cs.uni-bremen.de/teaching/mpar_literatur/), fie
tS durata executiei partii secventiale (executata de un singur procesor);
tP (p) durata executarii partii paralele utilizand p procesoare.
Durata executarii programului cu un sigur procesor este T1 = tS + tP (1), iar cu p procesoare, durata este Tp = tS + tP (p).
Raportat la durata totala de executie a programului cu un singur procesor, fractiunea
partii secventiale este
tS
,
A =
tS + tP (1)
si raportat la durata totala de executie a programului cu p procesoare, fractiunea partii
secventiale este
tS
G =
.
tS + tP (p)
In functie de cele doua exprimari, fractiunea partii paralele este
tP (1)
tS + tP (1)

1 A =
Apreciind ca tP (p) =

tP (1)
,
p

si respectiv 1 G =

tP (p)
.
tS + tP (p)

viteza algoritmica se exprima prin

Legea lui Amdahl


1
T1
tS + tP (1)
=
;
Sp =
=
t
(1)
A
Tp
A + 1
tS + P p
p
Legea lui Gustafson
T1
tS + ptP (p)
Sp =
= G + p(1 G ).
=
Tp
tS + tP (p)
Deoarece

1
A +

1A
p

1
A

din legea lui Amdahl rezulta ca Sp

1
,
A

adica viteza algoritmica

este marginita relativ la numarul de procesoare. Drept consecinta, scopul paralelizarii este
rezolvarea unor probleme de dimensiune din ce n ce mai mari si nu rezolvarea ntr-un
timp cat mai scurt a unei probleme de dimensiune fixata.
Pe de alta parte, deoarece orice program paralel are o parte secventiala, potrivit legii
lui Gustafson, viteza algoritmica este functie crescatoare relativ la p si Sp < p, adica
programul paralel are viteza algoritmica subliniara, neputandu-se obtine programe cu
viteza algoritmica liniara (Sp = p) si supraliniara (Sp > p).
Stabilirea acestor rezultate presupune faptul ca atat n varianta secventiala (p = 1)
cat si n varianta paralela (p > 1), programul executa aceleasi operatii.

189

IN JAVA
11.4. PROGRAMARE PARALELA

11.4

Programare paralel
a n Java

Limbajul de programare Java permite executia simultana a mai multor activitati prin
intermediul firelor de executie (thread).
Spre deosebire de un proces, un fir de executie nu presupune executia sa de catre un
procesor dedicat si toate firele de executie mpart acelasi spatiu de adrese. Fiecare fir de
executie are o stiva proprie pentru gestionarea metodelor apelate si a variabilelor locale.
Avand acelasi spatiu de adrese, firele de executie comunica prin variabile comune.
Utilizarea firelor de executie nu conduce la reducerea timpului de executie - mai ales
daca exista o singura unitate centrala. Intr-un program Java, rolul utilizarii firelor de
executie este separarea preocuparilor, adica simplificarea programarii. Este mai usor de
scris o secventa de cod pentru fiecare activitate a algoritmului, executarea lor trecand n
sarcina Masinii Virtuale Java si a sistemului de operare care simuleaza executia simultan
a.
Singura problema care ramane n sarcina programatorului este rezolvarea problemelor
de sincronizare ntre firele de executie.
Chiar n cazul unui calculator cu un procesor avand mai multe nuclee de calcul (multicore) gestionarea acestor nuclee nu cade n sarcina programatorului si nu exista nici o
certitudine ca executia este paralela.
Astfel utilizarea firelor de executie conduce doar la executie concurenta.
Pe un calculator obisnuit executie paralela se va obtine prin utilizarea procesorului
grafic. Daca metoda de calcul este iterativa atunci programarea va fi mai simpla prin
utilizarea unui algoritm paralel si iterativ asincron.

11.5

Metode numerice paralele

Scopul acestei sectiuni este prezentarea unor metode numerice care se pot paraleliza
prin descompunerea domeniului de calcul.
Rezolvarea unei probleme consta din executarea a N sarcini de calcul identice. Multimea
acestor sarcini, {0, 1, . . . , N 1}, reprezinta domeniul de calcul. Pentru efectuarea calculelor se vor utiliza p procese.
Fiecare proces i {0, 1, . . . , p 1} va efectua cel mult d Np e sarcini, unde


N
p


=

daca

N
p

N,

h i

N + 1 daca
p

N
p

/ N,

N
p

iar [a] reprezinta partea ntreaga a lui a.


Distributia celor N sarcini la cele p procese se poate face:
ciclic: sarcina j va fi executata de procesul j mod p, sau procesul i executa sarcinile
s p + i, s = 0, 1, . . . .
Pseudocodul procesului i este:

190

CAPITOLUL 11. INTRODUCERE IN PROGRAMAREA CONCURENTA

Calc(i)
pentru s = 0 : d Np e 1 executa
|
j sp+i
|
daca j N 1 atunci
|
|
executa sarcina j
|


stop
n bloc: sarcina j va fi executata de procesul j div d Np e, sau procesul i executa
sarcinile d Np e i + s, s = 0, 1, . . . , d Np e 1.
Pseudocodul procesului i este:
Calc(i)
pentru s = 0 : d Np e 1 executa
|
j d Np e i + s
|
daca j N 1 atunci
|
|
executa sarcina j
|


stop
Exemplul 11.5.1
Pentru N = 10 si p = 4 distribuirea sarcinilor este
sarcina 0 1 2 3 4 5 6 7
Cazul ciclic
procesul 0 1 2 3 0 1 2 3

8 9
0 1

sarcina 0 1 2 3 4 5 6 7 8 9
procesul 0 0 0 1 1 1 2 2 2 3
Un algoritm caruia i se poate aplica paralelizarea prin descompunerea domeniului de
calcul se numeste trivial paralel.
Metodele numerice de care ne ocupam constau n generarea unui sir de aproximatii pe
baza unei formule de recurenta
Cazul n blocuri

x(k+1) = F (x(k) ),
(k)

kN

iar x(k) = (xi )1iN . Paralelizarea se refera doar la calculul unei aproximatii pe baza
formulei de recurenta: cele N componente se calculeaza n N procese.
Global un algoritm va genera un sir finit de aproximatii potrivit unei reguli de oprire,
iar schema de trecere la o noua iteratie se poate face sincron sau asincron. In modul
sincron are loc o sincronizare bariera la sfarsitul calculului unei componente iar n modul
asincron aceasta sincronizare nu mai are loc.

191

11.5. METODE NUMERICE PARALELE

Metoda Jacobi pentru sisteme algebrice de ecuatii liniare


Fie A Mn (R) astfel ncat ai,i 6= 0, i {1, 2, . . . , n} si b Rn . Rezolvarea sistemului algebric de ecuatii liniare Ax = b prin metoda Jacobi consta n generarea sirului
(uk )kN , uk = (uk1 , . . . , ukn )T , prin formulele de recurenta

n
X
1

ai,j ukj
i {1, . . . , n},
(11.1)
uk+1
=
bi
i
ai,i
j=1
j6=i

k N, iar prima aproximatie u0 = (u01 , . . . , u0n )T este un


din Rn .
Pelement
n
Daca matricea A are diagonala dominanta, adica j=1 |ai,j | < |ai,i |, i = 1, 2, . . . , n,
j6=i

sau este simetrica si pozitiv definita, atunci convergenta procedeului (11.1) este asigurata.

Determinarea simultan
a a r
ad
acinilor unui polinom
Fie polinomul P C[X], P (z) = z n + a1 z n1 + . . . + an1 z + an . Notam prin
= (1 , 2 , . . . , n )T vectorul format de radacinile polinomului P, pe care le consideram
distincte doua cate doua, deci simple.
O clasa de metode pentru determinarea simultana a radacinilor polinomului P este
data de formula de recurenta
z (k+1) = T (z (k) ),

kN

unde T : C C, T (z) = (T1 (z), . . . , Tn (z))T este un operator ce defineste metoda.


Amintim metoda Durand-Kerner. Daca z = (z1 , . . . , zn )T atunci operatorul T corespunzator metodei Durand-Kerner este
Ti (z) = zi Q

P (zi )
,
j=1,n (zi zj )

i {1, . . . , n}.

j6=i

Formula de recurenta devene


(k)

(k+1)
zi

(k)
zi

Qn

P (zi )

j=1

j6=i

(k)

(zi

(k)

zj )

i {1, . . . , n},

k N.

Daca aproximatia initiala z (0) este aleasa ntr-o vecinatate convenabila a lui atunci sirul
de aproximatii (z (k) )kN converge catre .

192

CAPITOLUL 11. INTRODUCERE IN PROGRAMAREA CONCURENTA

Capitolul 12
Algoritm paralel si iterativ
Punem n evidenta doua clase de algoritmi paraleli si iterativi. Prezentare se refera la
calculul unui punct fix al unei functii.
Fie T : D Rn Rn o functie care admite un punct fix x D, T (x ) = x .
Calculul punctului fix va utiliza metoda aproximatiilor succesive
xk+1 = T (xk ),

(12.1)

pornind de la un element x0 D.
Fie r = kx0 x k. Daca
1.
2.

B(x , r) D;
kT (x) T (x )k kx x k,

x D,

atunci xk D, k N.
Varianta paralela va utiliza L n procese (fire de executie). Procesul i {1, . . . , L}
actioneaza asupra variabilelor (xj1 , . . . , xjni ) = xi si calculeaza termenii (Tk1 , . . . , Tkni ) =
Ti .
Notam Ji = {j1 , . . . , jni }, Ki = {k1 , . . . , kni }. Presupunem
ni=1 Ji = ni=1 Ki = {1, . . . , n},
si
i 6= j

Ji Jj =
.
Ki K j =

Renumerotam termenii si variabilele luand


J1 = K1 = {1, . . . , n1 }
J2 = K2 = {n1 + 1, . . . , n1 + n2 }
..
.
JL = KL = {n1 + . . . + nL1 , . . . , n1 + . . . + nL1 + nL = n}
Functia T se reprezinta prin T (x) = (Ti (x))1iL , x = (x1 , . . . , xL )T , xi Rni .
Un ciclu al unui algoritm paralel pentru calculul punctului fix utilizand sirul (12.1)
presupune doua faze:
193

194

CAPITOLUL 12. ALGORITM PARALEL S


I ITERATIV

de calcul procesul i calculeaza componenta xi


de comunicatie procesul i trimite componenta calculata celorlalte procese si receptioneaza
celelelte componente xj , j 6= i.
Faza de comunicatie se poate programa - functie de suportul hard/soft utilizand
memorie partajata,
mesaje.
Exista doua variante de realizare a unui algoritm paralel pentru calculul punctului fix
utilizand sirul (12.1):
sincron Dupa efectuarea fazei de calcul are loc o sincronizare de tip bariera, iar
apoi are loc faza de comunicatie. Sirul (xk )kN generat coincide cu cel furnizat de
un algoritm secvential. Faza de calcul a procesorului i consta din
xk+1
= Ti (xk1 , . . . , xkL )
i
asincron Se renunta la sincronizarea bariera.
Rezultatulde convergenta pentru o metoda bazata pe un algoritm paralel si iterativ
sincron coincide cu cel pentru metoda secventiala.

12.1

Algoritm paralel si iterativ asincron

Fiecare proces i poate contoriza ntr-un contor ki iteratiile pe care le executa. Odata
calculata componenta xki i +1 ea este trimisa celorlalte procese. Pentru calculul acestei
componente procesul i utilizeaza pentru xj , j 6= i valori care pot sa nu coincida cu
ultimele valori calculate, respectiv de procesele j 6= i.
Notam cu sij (ki ) indicele lui xj furnizat de procesul j procesului i, valoare utilizata
pentru calculul lui xki i +1 ,
si (ki )

xki i +1 = Ti (x11

si

i1
, . . . , xi1

(ki )

si

i+1
, xki i , xi+1

(ki )

si (ki )

, . . . , xLL

).

si (ki )

xj j

este utilizat de procesul i pana la receptia unei noi valori.


Pseudocodul procesului i este dat n Algoritmul 2. Algoritmul utilizeaza o metoda
convergence():boolean care depisteaza convergenta si contine o regula de oprire. Operatia
receive este presupusa neblocanta.
Presupunem ca
lim sij (ki ) = ,
i, j {1, . . . , L}.
(12.2)
ki

Semnificatia acestei restrictii este aceea ca n lipsa regulii de oprire, toate procesele conlucreaza, adica trimit si receptioneaza valori, niciun proces nu este lasat deoparte.

195

12.1. ALGORITM PARALEL S


I ITERATIV ASINCRON

Algorithm 2 Procesul i
1: procedure Proces(i, x0 )
2:
ki 0
3:
do
si (ki )
4:
receive xj j , j 6= i
5:
Compute xki i +1
6:
send xki i +1
7:
ki ki + 1
8:
while convergence()
9: end procedure
Q
Q
Consideram T : D Rn = Lj=1 Rnj Lj=1 Rnj , si notam norma din Rnj prin k kj
iar norma din Rn va fi kxk = max1jL kxj kj .
Presupunem ca exista [0, 1) astfel ncat
kT (x) T (x )k kx x k,

x D.

(12.3)

In fiecare proces i {1, . . . , L} se pune n evidenta subsirul (mi )lN prin


l
mi0 = 0
mil+1 = min{ki : sij (ki ) > mil , j 6= i}.
mi

xi l+1 se obtine dupa ce toate componenetele necesare calculului au fost rennoite. Semnificatia
inegalitatii sij (ki ) > mil consta n aceea ca procesul i a receptionat cel putin o valoare noua
i
pentru xj , dupa aceea utilizata pentru calcului lui xml .
i

si (k )

si

(ki )

mi

si

i1
i+1
Notam xml+1 = (x11 i , . . . , xi1
, xi l+1 , xi+1
Are loc urmatorul rezultat de convergenta:

(ki )

si (ki ) T

, . . . , xLL

) cu ki = mil+1 1.

ipotezele introduse, (12.2), (12.3), n fiecare proces liml xmil =


Teorema 12.1.1 (El Tarazi) In
x .
Demonstatie. Pentru i {1, . . . , L}, x1i = Ti (x0 ), de unde
kx1i xi ki = kTi (x0 ) Ti (x )ki max kTj (x0 ) Tj (x )kj =
1jL

= kT (x0 ) T (x )k kx0 x k,
i

si astfel kxm1 x k kx0 x k.


i
Aratam ca kxml x k l kx0 x k.
i
Dupa calculul elementului xml , procesul i va receptiona cel putin o valoare pentru xj ,
adica
si (ki )
sij (ki ) > mil kxj j
xj kj l+1 kx0 x k
j 6= i.

196

CAPITOLUL 12. ALGORITM PARALEL S


I ITERATIV

mil+1

xi ki =

Apoi kxi

si (ki )

= kTi ((x11

si (ki )

kT ((x11

(ki )

si

(ki )

i1
, . . . , xi1

si (ki )

k(x11

si

i1
, . . . , xi1

si

i1
, . . . , xi1

si

(ki )

si

(ki )

i+1
, xki i , xi+1

i+1
, xki i , xi+1

(ki )

si

i+1
, xki i , xi+1

si (ki ) T

) ) Ti (x )ki

, . . . , xLL

si (ki ) T

, . . . , xLL

(ki )

) ) T (x )k

si (ki ) T

, . . . , xLL

) x k

l+1 kx0 x k.
Astfel
i

mil+1

kxml+1 x k = max{kxi

si (ki )

xi ki , max kxj j
j6=i

xj kj } l+1 kx0 x k.

Capitolul 13
OpenCL prin Aparapi
Procesoarele grafice (Graphical Processing Unit - GPU ), unitatile de procesare (multicore Central Processing Unit) sunt utilizate n calculul paralel.
In acest sens au fost dezvoltate instrumente de programare:
CUDA - Compute Unified Device Arhitecture este o platforma si model de programare pentru procesoarele grafice Nvidia. CUDA este dezvoltat de Nvidia.
OpenCL - Open Computing Language este un standard de programare mentinut de
organizatia non-profit Khronos Group si vizeaza utilizarea unitatilor de procesare
(CPU) si a procesoarelor grafice (GPU). Dezvoltat initial de Apple n prezent este
adoptat de AMD, Intel, Nvidia, ARM Holdings.
Modelul de programare paralela este SIMD.
Fiecare instrument este reprezentat de biblioteci de functii iar limbajul de dezvoltare
este C.
Intel dezvolta arhitectura Many-Integrated-Core (MIC), destinat de asemenea calculului paralel.

13.1

Aparapi

Aparapi -(A PARallel API )1 este un cadru de lucru care permite programarea n Java
pentru platforma OpenCL - https://github.com/aparapi/aparapi/releases. Ideea
cadrului de lucru este convertirea codului Java n cod OpenCL n timpul executiei.
In functie de resursele existente pe calculatorul de lucru executia aplicatiei se va face
utilizand GPU sau ntr-un bazin de fire de executie JTP Java Thread Pool.
Pe un calculator cu placa grafica AMD este posibil ca pentru utilizarea GPU sa fie
necesara instalarea produsului AMD-APP-SDK-*.
Aparapi se distribuie sub forma unei arhive care trebuie dezarhivata. Arhiva contine
fisiere dll prin care se interactioneaza cu platforma OpenCL.
Compilarea unui program
1

apa rapi n indonezian


a nseamn
a ce ngrijit.

197

198

CAPITOLUL 13. OPENCL PRIN APARAPI

set APARAPI_DIR=. . .
javac -g -cp %APARAPI_DIR%\aparapi.jar *.java

Semnificatia optiunii -g este generarea tuturor informatiilor de depanare.


Lansarea n executie
java -Djava.library.path=%APARAPI_DIR% -cp %APARAPI_DIR%\aparapi.jar;. ClasaMain

Modul de procesare este redat n Fig. 13.1 (imagine preluata din QuickReference.pdf ).

Fig. 13.1: Modul de procesare aparapi

13.2

Programare n aparapi

Sablonul unui program aparapi este


import com.amd.aparapi.Kernel;
import com.amd.aparapi.Range;
public class NumeClasa{
public static void main(String[] _args) {
. . .
Kernel kernel = new Kernel(){
@Override
public void run() {
. . .
}
};
kernel.execute(Range.create(. . .));
System.out.println("Execution mode=" + kernel.getExecutionMode());

199

13.2. PROGRAMARE IN APARAPI

kernel.dispose();
. . .
}
}

Actiunea din metoda run a obiectului Kernel contine prelucrarea executata de o unitate
de procesare sau fir de executie, functie de modul de lucru.
Datele cu care se fac calcule trebuie sa fie de tip int sau float iar tablourile unidimensionale. Transformarea unei matrice mat Mr,c (T ) ntr-un vector v T rc prin
juxtapunerea liniilor se face prin formula
vic+j = mati,j ,

(i, j) {0, . . . , r 1} {0, . . . , c 1},

unde T {int,float}.

Clasa com.amd.aparapi.Kernel
Constructori
Kernel()
Metode
public abstract void run()
public Kernel.EXECUTION MODE getExecutionMode()
Evidentiaza modul lucru care poate fi GPU, JTP, CPU.
public Kernel execute(Range range)
public Kernel execute(Range range, int n)
range indica structura unitatilor de procesare, iar n indica numarul de cate ori se
executa mtoda run dintr-o unitate de procesare.
Clasa Kernel contine o familie de functii matematica de argument si valoare de tip
float, dar care nu pot fi utilizate decat n instantierea clasei. Functiile nlocuiesc pe cele
din clasa java.lang.Math care nu pot fi folosite.

Clasa com.amd.aparapi.Range
Specifica modul de organizare / gestiune a unitatilor de procesare. Metode
public static Range create(int globalWidth)
public static Range create2D(int globalWidth, int globalHeight)
public static Range create3D(int globalWidth, int globalHeight,
int globalDepth,)

200

CAPITOLUL 13. OPENCL PRIN APARAPI

13.3

Exemple

Tehnica de programare este ilustrata prin cateva exemple simple.

Produsul a dou
a matrice
Date fiind A Mm,n (Z), B Mn,p (Z) se calculeaza C = AB. Componentele matricei
C se calculeaza n paralel, fiecare componenta este calculata de o unitate de procesare
GPU,
n1
X
Ci,j =
Ai,k Bk,j , (i, j) {0, . . . , m 1} {0, . . . , p 1}.
k=0

Unitatile de procesare sunt organizate ntr-o matrice de dimensiune (m, p).


1
2
4
5
6
7
8
9
10
11

import com . amd . a p a r a p i . K e r n e l ;


import com . amd . a p a r a p i . Range ;
public c l a s s ProdMat{
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
f i n a l i n t m=3;
f i n a l i n t n=4;
f i n a l i n t p=5;
f i n a l i n t [ ] a=i n i t A (m, n ) ;
f i n a l i n t [ ] b=i n i t B ( n , p ) ;
f i n a l i n t [ ] c=new i n t [mp ] ;
K e r n e l k e r n e l = new K e r n e l ( ) {
@Override public void run ( ) {
int gidx = getGlobalId ( 0 ) ;
int gidy = getGlobalId ( 1 ) ;
i n t s =0;
f o r ( i n t k =0;k<n ; k++)
s+=a [ g i d x n+k ] b [ kp+g i d y ] ;
c [ g i d x p+g i d y ]= s ;
}
};

13
14
15
16
17
18
19
20
21
22

long i n c e p u t=System . c u r r e n t T i m e M i l l i s ( ) ;
k e r n e l . e x e c u t e ( Range . c r e a t e 2 D (m, p ) ) ;
long s f a r s i t =System . c u r r e n t T i m e M i l l i s ( ) ;

24
25
26

System . out . p r i n t l n ( E x e c u t i o n mode= + k e r n e l . getExecutionMode ( ) ) ;


kernel . dispose ( ) ;
System . out . p r i n t l n ( Durata : +( s f a r s i t i n c e p u t ) ) ;

28
29
30

System . out . p r i n t l n ( M a t r i c e a produs : ) ;


f o r ( i n t i = 0 ; i < m; i ++) {
f o r ( i n t j =0; j <p ; j ++)
System . out . p r i n t f ( %6d %1s , c [ i p+j ] , ) ;
System . out . p r i n t f ( \n ) ;
}

32
33
34
35
36
37
38

40

41
42
43
44
45
46
47

Transformarea u n e i m a t r i c e i n v e c t o r
prin juxtapunerea l i n i i l o r
/
private s t a t i c i n t [ ] i M a t 2 v e c t ( i n t [ ] [ ] mat ) {
i n t rows=mat . l e n g t h ;
i n t c o l s=mat [ 0 ] . l e n g t h ;
i n t [ ] v=new i n t [ rows c o l s ] ;

13.3. EXEMPLE

f o r ( i n t i =0; i <rows ; i ++){


f o r ( i n t j =0; j <c o l s ; j ++){
v [ i c o l s+j ]=mat [ i ] [ j ] ;
}
}
return v ;

48
49
50
51
52
53
54

56

57

74

I n i t i a l i z a r e a primei matrice A
/
private s t a t i c i n t [ ] i n i t A ( i n t m, i n t n ) {
i n t [ ] [ ] mat=new i n t [m ] [ n ] ;
i n t f a c t =1;
f o r ( i n t i =0; i <m; i ++){
f o r ( i n t j =0; j <n ; j ++){
mat [ i ] [ j ]= f a c t ( j +1);
}
f a c t =10;
}
System . out . p r i n t l n ( M a t r i c e a A : ) ;
f o r ( i n t i =0; i <m; i ++){
f o r ( i n t j =0; j <n ; j ++) System . out . p r i n t ( mat [ i ] [ j ]+ ) ;
System . out . p r i n t l n ( ) ;
}
return i M a t 2 v e c t ( mat ) ;
}

76

77

I n i t i a l i z a r e a c e l e i de a doua m a t r i c e B
/
private s t a t i c i n t [ ] i n i t B ( i n t m, i n t n ) {
i n t [ ] [ ] mat=new i n t [m ] [ n ] ;
i n t f a c t =1;
f o r ( i n t i =0; i <m; i ++){
f o r ( i n t j =0; j <n ; j ++){
mat [ i ] [ j ]=( i +1)( j +1);
}
}
System . out . p r i n t l n ( M a t r i c e a B : ) ;
f o r ( i n t i =0; i <m; i ++){
f o r ( i n t j =0; j <n ; j ++) System . out . p r i n t ( mat [ i ] [ j ]+ ) ;
System . out . p r i n t l n ( ) ;
}
return i M a t 2 v e c t ( mat ) ;
}

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

201

In cod initializarea este facuta n mod convenabil pentru verificarea facila a rezultatelor.
Codul fisierului de comenzi al executiei este
1
2
3
4
5

s e t ProgName=ProdMat
d e l %ProgName%. c l a s s
s e t APARAPI DIR=. . .
j a v a c g cp %APARAPI DIR%\a p a r a p i . j a r %ProgName%. j a v a
j a v a Djava . l i b r a r y . path=%APARAPI DIR% cp %APARAPI DIR%\a p a r a p i . j a r ; . %ProgName%

202

CAPITOLUL 13. OPENCL PRIN APARAPI

Calculul unei integrale prin metoda trapezelor


Fie f : [a, b] R o functie continua. Pentru un numar m N , metoda trapezelor
consta din calculul expresiei Im (f, a, b), unde
Z

m1

X
ba
[f (a) + 2
f (a + ih) + f (b)].
f (x)dx Im (f, a, b) =
2m
i=1

Algoritmul care va fi utilizat n program foloseste datele


size N ;
ba
i = a + i size
, i {0, 1, . . . , size};

si calculeaza sirul partiali = Im (f, i , i+1 ). In final


Z

f (x)dx =
a

size1
X Z i+1
i=0

f (x)dx

size1
X

partiali .

i=0

Unitatile de procesare sunt organizate ca un vector de dimensiune size.


Codup aplicatiei este
1
2
4
5
6
7
8
10
11
12
13
14
15
16

import com . amd . a p a r a p i . K e r n e l ;


import com . amd . a p a r a p i . Range ;
public c l a s s I n t e g {
public s t a t i c void main ( S t r i n g [ ]
args ) {
f i n a l i n t s i z e =16;
f i n a l f l o a t [ ] data ={0.0 f , 0 . 2 5 f ( f l o a t ) Math . PI } ;
f i n a l f l o a t [ ] p a r t i a l=new f l o a t [ s i z e ] ;
K e r n e l k e r n e l = new K e r n e l ( ) {
/
D e f i n i r e a f u n c t i e i de i n t e g r a t
/
float f c t ( float x ){
return l o g (1+ tan ( x ) ) ;
}
/

18

Formula t r a p e z e l o r a p l i c a t a f u n c t i e i f c t
i n i n t e r v a l u l [ a , b ] cu p a r a m e t r u l de d i s c r e t i z a r e m

19
20

/
f l o a t t r a p e z e ( f l o a t a , f l o a t b , i n t m) {
f l o a t s =0 ,h=(ba ) /m;
f o r ( i n t i =1; i <m; i ++) s+=f c t ( a+i h ) ;
return 0 . 5 f h ( f c t ( a )+2 s+f c t ( b ) ) ;
}

21
22
23
24
25
26

@Override
public void run ( ) {
int gid = getGlobalId ( ) ;
f l o a t h=( data [ 1 ] data [ 0 ] ) / s i z e ;
f l o a t a=data [ 0 ] + h g i d ;
f l o a t b=a+h ;
p a r t i a l [ g i d ]= t r a p e z e ( a , b , 5 0 0 ) ;
}

28
29
30
31
32
33
34
35
36

};

203

13.3. EXEMPLE

40

k e r n e l . e x e c u t e ( Range . c r e a t e ( s i z e ) ) ;
System . out . p r i n t l n ( E x e c u t i o n mode= + k e r n e l . getExecutionMode ( ) ) ;
kernel . dispose ( ) ;

42

43

Insumarea r e z u l t a t e l o r p a r t i a l e
/
f l o a t i n t e g =0;
f o r ( i n t i = 0 ; i < s i z e ; i ++) {
i n t e g+=p a r t i a l [ i ] ;
}

38
39

44
45
46
47
48

System . out . p r i n t f ( I n t e g r a l a = %10.4 f \n , i n t e g ) ;

50

51
52

Rezolvarea sistemelor algebrice de ecuatii liniare


prin metoda Jacobi
A Mn (Z), b Rn . Pentru rezolvarea sistemului Ax = b potrivit metodei Jacobi se
construiesc sirurile
(k+1)
ui

n
X
1
(k)
(bi
ai,j uj ),
=
ai,i
j=1,j6=i

i {1, . . . , n}, k N.

Algoritmul va fi paralel si iterativ asincron, numarul


in final se va determina un indicator de raspuns.
Problema de test este

9 1 3 1 3
2 8 0 1 3

2 2

7
1
1
x
=

4 1 1 9 2

1 3 0 2 6

iteratiilor va fi fixat a priori iar

5
15
16
20
1

cu solutia x = (1, 2, 1, 3, 0)T .


Aplicatia are codul
1
2
4
5
6
7
8
9
10
11
12
13
15
16
17
18

import com . amd . a p a r a p i . K e r n e l ;


import com . amd . a p a r a p i . Range ;
public c l a s s J a c o b i A s y n c {
public s t a t i c void main ( S t r i n g [ ]
args ) {
f i n a l f l o a t [ ] a=i n i t A ( ) ;
f i n a l f l o a t [ ] b=i n i t B ( ) ;
f i n a l i n t n=b . l e n g t h ;
// A f i s a r e a d a t e l o r s i s t e m u l u i
f o r ( i n t i =0; i <n ; i ++){
f o r ( i n t j =0; j <n ; j ++) System . out . p r i n t ( a [ i n+j ]+ ) ;
System . out . p r i n t l n ( <> +b [ i ] ) ;
}
final
final
final
float

f l o a t [ ] x=new f l o a t [ n ] ;
f l o a t [ ] y=new f l o a t [ n ] ;
f l o a t [ ] e r r o r s=new f l o a t [ n ] ;
t o l =1e5f , nrm=0.0 f ;

204

CAPITOLUL 13. OPENCL PRIN APARAPI

19

i n t nmi =50;

21

K e r n e l k e r n e l = new K e r n e l ( ) {
@Override public void run ( ) {
int gid = getGlobalId ( ) ;
f o r ( i n t i =0; i <n ; i ++)x [ i ]=y [ i ] ;
f l o a t s =0;
f o r ( i n t i =0; i <n ; i ++){
i f ( i != g i d ) s+=a [ g i d n+i ] x [ i ] ;
}
y [ g i d ]=( b [ g i d ] s ) / a [ g i d n+g i d ] ;
e r r o r s [ g i d ]=Math . abs ( y [ g i d ]x [ g i d ] ) ;
}
};

22
23
24
25
26
27
28
29
30
31
32

// Aproximatia i n i t i a l a
f o r ( i n t i =0; i <n ; i ++) y [ i ] = 0 . 0 f ;
long i n c e p u t=System . c u r r e n t T i m e M i l l i s ( ) ;
k e r n e l . e x e c u t e ( Range . c r e a t e ( n ) , nmi ) ;
long s f a r s i t =System . c u r r e n t T i m e M i l l i s ( ) ;
System . out . p r i n t l n ( E x e c u t i o n mode= + k e r n e l . getExecutionMode ( ) ) ;
kernel . dispose ( ) ;
System . out . p r i n t l n ( Durata : +( s f a r s i t i n c e p u t ) ) ;

34
35
36
37
38
39
40
41

System . out . p r i n t l n ( S o l u t i a : ) ;
f o r ( i n t i = 0 ; i < n ; i ++) {
System . out . p r i n t f ( %10.4 f \n , y [ i ] ) ;
}
f o r ( i n t i =0; i <n ; i ++)nrm=Math . max( nrm , e r r o r s [ i ] ) ;
i n t i n d =0;
i f ( nrm>=t o l ) i n d =1;
System . out . p r i n t l n ( I n d i c a t o r u l de r a s p u n s : +i n d ) ;

43
44
45
46
47
48
49
50
51

53

/
Transformarea u n e i m a t r i c e i n v e c t o r
prin juxtapunerea l i n i i l o r

54
55

/
private s t a t i c f l o a t [ ] f M a t 2 v e c t ( f l o a t [ ] [ ] mat ) { . . . }

56
57

59

66

I n i t i a l i z a r e a matricei A
/
private s t a t i c f l o a t [ ] i n i t A ( ) {
f l o a t [ ] [ ] mat = { { 9 , 1 , 3 , 1 , 3 } , { 2 , 8 , 0 , 1 , 3 } , { 2 , 2 , 7 , 1 , 1 } , { 4 , 1 , 1 , 9 , 2 } , { 1 , 3 , 0 , 2 , 6 } } ;
i n t n=mat . l e n g t h ;
return f M a t 2 v e c t ( mat ) ;
}

68

69

Initializarea vectorului b
/
private s t a t i c f l o a t [ ] i n i t B ( ) {
f l o a t [ ] mat ={ 5 , 15 ,16 ,20 ,1};
return mat ;
}

60
61
62
63
64
65

70
71
72
73
74
75

Varianta paralela si iterativ sincrona are codul


1
2
4
5
6
7

import com . amd . a p a r a p i . K e r n e l ;


import com . amd . a p a r a p i . Range ;
public c l a s s J a c o b i S y n c {
public s t a t i c void main ( S t r i n g [ ]
f i n a l f l o a t [ ] a=i n i t A ( ) ;
f i n a l f l o a t [ ] b=i n i t B ( ) ;

args ) {

13.3. EXEMPLE

f i n a l i n t n=b . l e n g t h ;
// A f i s a r e a d a t e l o r s i s t e m u l u i
f o r ( i n t i =0; i <n ; i ++){
f o r ( i n t j =0; j <n ; j ++) System . out . p r i n t ( a [ i n+j ]+ ) ;
System . out . p r i n t l n ( <> +b [ i ] ) ;
}

8
9
10
11
12
13

f i n a l f l o a t [ ] x=new f l o a t [ n ] ;
f i n a l f l o a t [ ] y=new f l o a t [ n ] ;
f i n a l f l o a t [ ] e r r o r s=new f l o a t [ n ] ;
f l o a t t o l =1e5f , nrm=0.0 f ;
i n t nmi =50;

15
16
17
18
19

K e r n e l k e r n e l = new K e r n e l ( ) {
@Override public void run ( ) {
int gid = getGlobalId ( ) ;
f o r ( i n t i =0; i <n ; i ++)x [ i ]=y [ i ] ;
f l o a t s =0;
f o r ( i n t i =0; i <n ; i ++){
i f ( i != g i d ) s+=a [ g i d n+i ] x [ i ] ;
}
y [ g i d ]=( b [ g i d ] s ) / a [ g i d n+g i d ] ;
e r r o r s [ g i d ]=Math . abs ( y [ g i d ]x [ g i d ] ) ;
}
};

21
22
23
24
25
26
27
28
29
30
31
32

// Aproximatia i n i t i a l a
f o r ( i n t i =0; i <n ; i ++) y [ i ] = 0 . 0 f ;
long i n c e p u t=System . c u r r e n t T i m e M i l l i s ( ) ;

34
35
36

i n t i t e r =0;
do{
i t e r ++;
k e r n e l . e x e c u t e ( Range . c r e a t e ( n ) ) ;
nrm=0.0 f ;
f o r ( i n t i =0; i <n ; i ++) nrm=Math . max( nrm , e r r o r s [ i ] ) ;
// System . o u t . p r i n t l n ( I t e r : + i t e r + Norma e r o r i i : +nrm ) ;
}
while ( ( t o l <=nrm)&&( i t e r <nmi ) ) ;
long s f a r s i t =System . c u r r e n t T i m e M i l l i s ( ) ;
System . out . p r i n t l n ( Durata : +( s f a r s i t i n c e p u t ) ) ;
System . out . p r i n t l n ( E x e c u t i o n mode= + k e r n e l . getExecutionMode ( ) ) ;
kernel . dispose ( ) ;

38
39
40
41
42
43
44
45
46
47
48
49
50

System . out . p r i n t l n ( S o l u t i a : ) ;
f o r ( i n t i = 0 ; i < n ; i ++) {
System . out . p r i n t f ( %10.4 f \n , y [ i ] ) ;
}
i n t i n d =0;
i f ( nrm>=t o l ) i n d =1;
System . out . p r i n t l n ( I n d i c a t o r u l de r a s p u n s : +i n d ) ;

52
53
54
55
56
57
58
59

61

/
Transformarea u n e i m a t r i c e i n v e c t o r
prin juxtapunerea l i n i i l o r

62
63
65

/
private s t a t i c f l o a t [ ] f M a t 2 v e c t ( f l o a t [ ] [ ] mat ) { . . . }

67

68
70

I n i t i a l i z a r e a matricei A
/
private s t a t i c f l o a t [ ] i n i t A ( ) { . . . }

72

64

69

Initializarea vectorului b

73
74

205

206

private s t a t i c f l o a t [ ]

75
76

CAPITOLUL 13. OPENCL PRIN APARAPI

initB (){. . .}

Se constata ca durata de executie a variantei sincrone este putin mai mare decat a
variantei asincrone.

Produsele informatice utilizate


Pe durata existentei, produsele informatice evolueaza prin versiunile pe care producatorii ni le pun la dispozitie. Nu de putine ori o versiune noua nu este compatibila cu
versiunea anterioara, fapt care necesita adaptarea programelor client.
Lista urmatoare precizeaza versiunile produselor utilizate n lucrare, indicate n majoritatea cazurilor prin resursa de instalare.

No.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

Versiunile produselor informatice utilizate n lucrare


Produsul informatic
Resursa/versiunea
apache-ant
apache.ant-1.9.6-bin.tar.gz
apache-commons-fileupload
commons-fileupload-1.3.1-bin.tar.gz
apache-commons-math
commons-math3-3.6.1-bin.tar.gz
apache-karaf
apache-karaf-4.0.4.zip
apache-maven
apache-maven-3.3.9-bin.tar.gz
apache-tomcat
apache-tomcat-8.0.32.tar.gz
aparapi
dist windows x86 64.zip
felix
felix-framework-5.4.0.tar.gz
glassfish
glassfish-4.1.1.zip
Google Web Toolkit
gwt-2.7.0.zip
Google App Engine
appengine-java-sdk-1.3.2.zip
httpcomponents-client
httpcomponents-4.5.1.tar.gz
Jama
Jama-1.0.3.jar
Java
jdk-8u77-windows-x64.exe
Java Expression Parser (JEP)
jep-2.4.1-ext-1.1.1-gpl.zip
jersey
jersey-ri-2.22.1.zip
jfreechart
jfreechart-1.0.19.zip
junit
junit-4.12.zip
Maple
Maple18WindowsInstaller.exe
MathEclipse parser
matheclipse-parser-0.0.10.jar
Mathematica
Mathematica 9.0.1 WIN.exe
metro
metro-standalone-2.3.1.zip
NetBeans
netbeans-8.1-javaee-windows.exe
PtPlot
ptplot5.10.tar.gz
Scilab
scilab-5.5.2.exe
symja
COMMONS MATH4 SYMJA.jar
symja java8-2016-03-20.jar

207

208

CAPITOLUL 13. OPENCL PRIN APARAPI

No.
27

Produsul informatic
visad

Resursa/versiunea
visad.jar

Bibliografie
[1] ANISIU V., 2006, Calcul simbolic cu Maple. Ed. Presa Universitara Clujeana, ClujNapoca.
[2] BOIAN F.M., BOIAN R. F., 2004, Tehnologii fundamentale Java pentru aplicatii
Web. Ed. Albastra, Cluj-Napoca.
[3] KINCAID D., CHENEY W., 1991, Numerical Analysis. Mathematics of scientific
computing. Brooks/Cole, Pacific Grove, California.
[4] LANDAU H. R., 2005, A First Course in Scientific Computing. Symbolic, Graphic,
and Numeric Modeling Using Maple, Java, Mathematica, and Fortran90. Princeton
Univ. Press, Princeton.

[5] MARUS
TER St., 1981, Metode numerice n rezolvarea ecuatiilor neliniare. Ed.
tehnica, Bucuresti.
[6] PETCU D., 2000, Matematica asistata de calculator. Ed. Eubeea, Timisoara.
[7] PRESS W. H., TEUKOLSKI S. A., VETTERING W. T., FLANNERY B. P., 2007,
Numerical Recipies 3rd Edition: The Art of Scientific Computation. Cambridge
University Press, Cambridge.
[8] RICHARSON L. J., 2003, Visualizing Complex Functions. http://web.archive.
org/web/20030802162645/physics.hallym.ac.kr/education/TIPTOP/VLAB/
QmSct/complex.html.
[9] SCHEIBER E., 2007, Programare concurenta si paralel-distribuita n Java. Ed. Albastra, Cluj-Napoca.
[10] SCHEIBER E., 2010, Java n calculul stiintific. Ed. Universitii Transilvania Brasov.
[11] STANCU D. D., COMAN G., (Ed), 2001, Analiza numerica si teoria aproximarii.
Vol. I, II, III, Ed. Presa Universitara Clujeana, Cluj-Napoca.
[12] TOCCI C., ADAMS S., 1996, Applied Maple for Engineers and Scientist. Artech
House, Boston, London.
[13] ***, http://en.wikipedia.org/wiki/List_of_numerical_analysis_software.
209

210

BIBLIOGRAFIE

[14] ***,
http://en.wikipedia.org/wiki/Comparison_of_numerical_analysis_
software.
Majoritatea produselor utilizate contin documentatie de utilizare, prezentarea tehnica
a interfetelor de programare (API), etc. La acestea se adauga multe alte referinte n
Internet.

You might also like