Arageli: Library for Doing Exact Computation Segrey S. Lyalin - - PowerPoint PPT Presentation

arageli
SMART_READER_LITE
LIVE PREVIEW

Arageli: Library for Doing Exact Computation Segrey S. Lyalin - - PowerPoint PPT Presentation

Arageli: Library for Doing Exact Computation Segrey S. Lyalin Nikolai Yu. Zolotykh University of Nizhni Novgorod, Russia ICMS, 2006 Contents 1 Project 3 2 Classes 4 3 Algorithms 6 4 Examples 8 5 Aragelis (distinctive)


slide-1
SLIDE 1

Arageli:

Library for Doing Exact Computation Segrey S. Lyalin Nikolai Yu. Zolotykh

University of Nizhni Novgorod, Russia ICMS, 2006

slide-2
SLIDE 2

Contents

1 Project 3 2 Classes 4 3 Algorithms 6 4 Examples 8 5 Arageli’s (distinctive) characteristics 29 6 Comparison with other libraries 30 7 Arageli in action 31

slide-3
SLIDE 3

1 Project

Arageli is a C++ library for exact computations in ARithmetic, Algebra, GEometry, Linear and Integer linear programming Sphere of possible applications: exact linear algebra, number theory, linear and integer linear programming, criptography, symbolic computations 100+ files of source code, 50000+ lines

slide-4
SLIDE 4

1 Project

Arageli is a C++ library for exact computations in ARithmetic, Algebra, GEometry, Linear and Integer linear programming Sphere of possible applications: exact linear algebra, number theory, linear and integer linear programming, criptography, symbolic computations 100+ files of source code, 50000+ lines

Arageli group

Eugene Agafonov Max Alekseyev (Uni of San Diego at pres.) Aleksey Bader Sergey S. Lyalin Aleksey Polovinkin Andrey Somsikov Nikolai Yu. Zolotykh                    University of Nizhni Novgorod

slide-5
SLIDE 5

2 Classes

slide-6
SLIDE 6

2 Classes

  • big int

Arbitrary precision integers

slide-7
SLIDE 7

2 Classes

  • big int

Arbitrary precision integers

  • rational<T>

Rational numbers/functions, i.e. fractions u v , where u, v ∈ T (integers/polynomials)

slide-8
SLIDE 8

2 Classes

  • big int

Arbitrary precision integers

  • rational<T>

Rational numbers/functions, i.e. fractions u v , where u, v ∈ T (integers/polynomials)

  • vector<T>

Vectors with entries that belong to T

slide-9
SLIDE 9

2 Classes

  • big int

Arbitrary precision integers

  • rational<T>

Rational numbers/functions, i.e. fractions u v , where u, v ∈ T (integers/polynomials)

  • vector<T>

Vectors with entries that belong to T

  • matrix<T>

Matrices with entries that belong to T

slide-10
SLIDE 10

2 Classes

  • big int

Arbitrary precision integers

  • rational<T>

Rational numbers/functions, i.e. fractions u v , where u, v ∈ T (integers/polynomials)

  • vector<T>

Vectors with entries that belong to T

  • matrix<T>

Matrices with entries that belong to T

  • sparse polynom<T>

Sparse polynomials with coefficients that belong to T

slide-11
SLIDE 11

2 Classes

  • big int

Arbitrary precision integers

  • rational<T>

Rational numbers/functions, i.e. fractions u v , where u, v ∈ T (integers/polynomials)

  • vector<T>

Vectors with entries that belong to T

  • matrix<T>

Matrices with entries that belong to T

  • sparse polynom<T>

Sparse polynomials with coefficients that belong to T

  • residue<T>

Elements in T modulo certain m ∈ T

slide-12
SLIDE 12

2 Classes

  • big int

Arbitrary precision integers

  • rational<T>

Rational numbers/functions, i.e. fractions u v , where u, v ∈ T (integers/polynomials)

  • vector<T>

Vectors with entries that belong to T

  • matrix<T>

Matrices with entries that belong to T

  • sparse polynom<T>

Sparse polynomials with coefficients that belong to T

  • residue<T>

Elements in T modulo certain m ∈ T

  • algebraic<T>

Algebraic numbers, i.e. roots of polynomials with coefficients in T = {rational numbers}

slide-13
SLIDE 13

2 Classes

  • big int

Arbitrary precision integers

  • rational<T>

Rational numbers/functions, i.e. fractions u v , where u, v ∈ T (integers/polynomials)

  • vector<T>

Vectors with entries that belong to T

  • matrix<T>

Matrices with entries that belong to T

  • sparse polynom<T>

Sparse polynomials with coefficients that belong to T

  • residue<T>

Elements in T modulo certain m ∈ T

  • algebraic<T>

Algebraic numbers, i.e. roots of polynomials with coefficients in T = {rational numbers}

slide-14
SLIDE 14
  • a few experimental classes (dense polynomials, polynomials of many variables,

algebraic numbers, multiprecision float point numbers, . . . )

slide-15
SLIDE 15
  • a few experimental classes (dense polynomials, polynomials of many variables,

algebraic numbers, multiprecision float point numbers, . . . ) All classes above (except big int) have more than 1 parameter. Supplementary parameters control reducing fractions algorithms, references count methods, etc.

slide-16
SLIDE 16

3 Algorithms

  • GCD (extended) Euclidian and binary algorithms
  • Gaussian elimination and Gauss-Bareiss’ elimination algorithms for matrices over

field and integer domains

  • Classical/Storjohann’s algorithms for constructing Smith’s normal diagonal form
  • ver ring of integers and ring of polynomials
  • Classical/Domich/Storjohann’s algorithms for finding Hermith’s normal form
  • Solovay–Strassen, Miller–Rabin and Agrawal–Kayal–Saxena tests for primality
  • Integer number factorization by Pollard’s ρ-method and Pollard’s p − 1 method
  • Simplex method and Gomory’s algorithms for linear and integer linear programming

problems

  • Sturm’s algorithm for locating polynomial roots
  • Double description method for polyhedra
  • Triangulation of polyhedra
  • . . .
slide-17
SLIDE 17
  • All algorithms are templated functions

int a, b; big int c, d; polynomial<rational<> > f, g; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . gcd(a, b); gcd(c, d); gcd(a, c); gcd(f, g);

slide-18
SLIDE 18
  • All algorithms are templated functions

int a, b; big int c, d; polynomial<rational<> > f, g; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . gcd(a, b); gcd(c, d); gcd(a, c); gcd(f, g);

  • One of parameters is controller: it is a class that controls the algorithm while it is

working, puts out intermediate results of the computation, measures time etc.

slide-19
SLIDE 19

4 Examples

slide-20
SLIDE 20

4 Examples

Example: big integers

#include <arageli/arageli.hpp> using namespace std; using namespace Arageli; int main(int argc, char *argv[ ]) { big int a = “101100111000111100001111100000”; big int b = “-1234567890987654321”; cout << “a = ” << a << endl << “b = ” << b << endl; cout << “2*(a + b) - a%b = ” << 2*(a + b) − a%b << endl; return 0; } a = 101100111000111100001111100000 b = -1234567890987654321 2*(a + b) - a%b = 202200221996782640900764076427

slide-21
SLIDE 21

Example: rational numbers

#include <arageli/arageli.hpp> using namespace std; using namespace Arageli; int main(int argc, char *argv[ ]) { rational<> a = “22/7”; rational<> b(355, 113); cout << “a = ” << a << endl; cout << “b = ” << b << endl; cout << “Numerator of a = ” << a.numerator() << endl; cout << “Denominator of a = ” << a.denominator() << endl; double af = a; // You can assign rational numbers to float or to double double bf = b; cout << “af = ” << setprecision(5) << af << endl; cout << “bf = ” << setprecision(10) << bf << endl; return 0; }

slide-22
SLIDE 22

a = 22/7 b = 355/113 Numerator of a = 22 Denominator of a = 7 af = 3.1429 bf = 3.14159292

slide-23
SLIDE 23

Example: polynomials

#include “arageli/arageli.hpp” using namespace std; using namespace Arageli; int main(int argc, char *argv[ ]) { sparse polynom<rational<> > f = “x^6+x^4-x^2-1”, g = “x^3-2*x^2-x+2”; cout << “f = ” << f << endl; cout << “g = ” << g << endl << endl; cout << “f + g = ” << f + g << endl; cout << “f - g = ” << f − g << endl; cout << “f * g = ” << f * g << endl; cout << “f / g = ” << f / g << endl; cout << “f % g = ” << f % g << endl; cout << “GCD(f, g) = ” << gcd(f, g) << endl; cout << “LCM(f, g) = ” << lcm(f, g) << endl; return 0; }

slide-24
SLIDE 24

f = x^6+x^4-x^2-1 g = x^3-2*x^2-x+2 f + g = x^6+x^4+x^3-3*x^2-x+1 f - g = x^6+x^4-x^3+x^2+x-3 f * g = x^9-2*x^8-2*x^5+4*x^4+x-2 f / g = x^3+2*x^2+6*x+12 f % g = 25*x^2-25 GCD(f, g) = x^2-1 LCM(f, g) = x^7-2*x^6+x^5-2*x^4-x^3+2*x^2-x+2

slide-25
SLIDE 25

Example: vectors and matrices

#include <arageli/arageli.hpp> using namespace std; using namespace Arageli; typedef rational<> Q; int main(int argc, char *argv[ ]) { matrix<Q> A = “((-1/2, 3/4), (-2/3, 5), (1/7, -5/2))”; matrix<Q> B = “((3/4, 1/6, -7/8), (5/2, 2/5, -9/10))”; vector<Q> c = “(1/4, -4/15, 5)”; vector<Q> d = “(-2/3, -1, 4)”; Q alpha = Q(1, 120), beta = −2; vector<Q> res = ((A*B)*c + d*(A*B) − alpha*d)/beta; // (A*B)*c → c is interpreted as a column // d*(A*B) → d is interpreted as a row cout << “Result:” << endl;

  • utput aligned(cout, res);

return 0;

slide-26
SLIDE 26

} Result: ||968591/50400|| ||174007/15120|| ||-27583/2520 ||

slide-27
SLIDE 27

Example: Smith’s normal diagonal form

Integer matrices #include <arageli/arageli.hpp> using namespace std; using namespace Arageli; int main(int argc, char *argv[ ]) { matrix<big int> A, B, P, Q; size t rk; sparse polynom<rational<> > d; A = “((0,6,-9), (12,24,9), (30,42,45))”; smith(A, B, P, Q, rk, d); // B = PAQ cout << “A = ” << endl; output aligned(cout, A); cout << “B = ” << endl; output aligned(cout, B); cout << “P = ” << endl; output aligned(cout, P); cout << “Q = ” << endl; output aligned(cout, Q);

slide-28
SLIDE 28

cout << “d = ” << d << endl; return 0; } A = ||0 6

  • 9||

||12 24 9 || ||30 42 45|| B = ||3 0 0 || ||0 6 0 || ||0 0 18|| P = ||-1 0 0|| ||11 1 0|| ||18 -1 1|| Q = ||0 -7 15|| ||1 3

  • 6||

||1 2

  • 4||

d = 324

slide-29
SLIDE 29

Polynomial matrices #include <arageli/arageli.hpp> using namespace std; using namespace Arageli; int main(int argc, char *argv[ ]) { matrix< sparse polynom<rational<> > > A, B, P, Q; size t rk; sparse polynom<rational<> > d; A = “((4-x,6,-15), (1,3-x,-5), (1,2,-4-x))”; smith(A, B, P, Q, rk, d); // B = PAQ cout << “A = ” << endl; output aligned(cout, A); cout << “B = ” << endl; output aligned(cout, B); cout << “P = ” << endl; output aligned(cout, P); cout << “Q = ” << endl; output aligned(cout, Q); cout << “d = ” << d << endl;

slide-30
SLIDE 30

return 0; } A = ||-x+4 6

  • 15 ||

|| 1

  • x+3
  • 5 ||

|| 1 2

  • x-4||

B = ||1 || ||0 x-1 || ||0 x^2-2*x+1|| P = ||-1/15 0 0 || || 1/3

  • 1 0 ||

||-x-2

  • 6 15||

Q = ||0 1 || ||0 1 1/3 || ||1 2/5 -1/15*x+2/5|| d = -x^3+3*x^2-3*x+1

slide-31
SLIDE 31

Example: modular arithmetic

#include <arageli/arageli.hpp> using namespace std; using namespace Arageli; int main(int argc, char *argv[ ]) { { // Working in Z5 = Z/5Z residue<int> a = “2 (mod 5)”; residue<int> b = “3 (mod 5)”; cout << “a = ” << a << endl; cout << “b = ” << b << endl; cout << “a + b = ” << a + b << endl; cout << “a - b = ” << a − b << endl; cout << “a * b = ” << a * b << endl; cout << “a / b = ” << a / b << endl << endl; }

slide-32
SLIDE 32

{ // Working in Q[x]/(x2 + 1)Q[x] typedef residue<sparse polynom<rational<> > > T; T a = “((1+x) (mod (x^2+1)))”; T b = “((1-x) (mod (x^2+1)))”; cout << “a = ” << a << “b = ” << b << endl; cout << “a + b = ” << a + b << endl; cout << “a - b = ” << a − b << endl; cout << “a * b = ” << a * b << endl; cout << “a / b = ” << a / b << endl << endl; } { // Working in Z3[x]/(x2 + 1)Z3[x] typedef residue<sparse polynom<residue<int> > > T; T a = “( ((1(mod 3))*x+(1(mod 3))) (mod ((1(mod 3))*x^2+(1(mod 3)))) )”; T b = “( ((1(mod 3))*x+(2(mod 3))) (mod ((1(mod 3))*x^2+(1(mod 3)))) )”; cout << “a = ” << a << endl << “b = ” << b << endl; cout << “a + b = ” << a + b << endl; cout << “a - b = ” << a − b << endl; cout << “a * b = ” << a * b << endl; cout << “a / b = ” << a / b << endl << endl; }

slide-33
SLIDE 33

} a = 2(mod 5) b = 3(mod 5) a + b = 0(mod 5) a - b = 4(mod 5) a * b = 1(mod 5) a / b = 4(mod 5) a = x+1(mod x^2+1)b = -x+1(mod x^2+1) a + b = 2(mod x^2+1) a - b = 2*x(mod x^2+1) a * b = 2(mod x^2+1) a / b = x(mod x^2+1) a = x+1(mod +3)(mod x^2+1(mod +3)) b = x+2(mod +3)(mod x^2+1(mod +3)) a + b = 2(mod 3)*x(mod x^2+1(mod +3)) a - b = 2(mod 3)(mod x^2+1(mod +3)) a * b = 1(mod 3)(mod x^2+1(mod +3)) a / b = 2(mod 3)*x(mod x^2+1(mod +3))

slide-34
SLIDE 34

Example: linear system over finite field

#include <arageli/arageli.hpp> using namespace std; using namespace Arageli; int main(int argc, char *argv[ ]) { typedef residue<int> T; int mod = 7; // Solving a linear system Ax = b over Z7 matrix<T> A = “((3, 1, 2), (1, 2, 3), (4, 3, 2))”; vector<T> b = “(1, 1, 1)”; vector<T> x; for(matrix<T>::iterator i = A.begin(); i < A.end(); ++i) { i− >module() = mod; i− >normalize(); }

slide-35
SLIDE 35

for(matrix<T>::iterator i = b.begin(); i < b.end(); ++i) { i− >module() = mod; i− >normalize(); } cout << “A = ” << endl; output aligned(cout, A); cout << endl; cout << “b = ” << endl; output aligned(cout, b); cout << endl; try { x = solve linsys(A, b); cout << “x = ” << endl;

  • utput aligned(cout, x);

cout << endl; cout << “Check the result: ” << boolalpha << (A*x == b) << endl; } catch(matrix is singular) { cout << “Error! Matrix is singular!” << endl; } return 0;

slide-36
SLIDE 36

} A = ||3(mod 7) 1(mod 7) 2(mod 7)|| ||1(mod 7) 2(mod 7) 3(mod 7)|| ||4(mod 7) 3(mod 7) 2(mod 7)|| b = ||1(mod 7)|| ||1(mod 7)|| ||1(mod 7)|| x = ||2(mod 7)|| ||6(mod 7)|| ||5(mod 7)|| Check the result: true

slide-37
SLIDE 37

Example: using iterators

#include <arageli/arageli.hpp> using namespace std; using namespace Arageli; int main(int argc, char *argv[ ]) { typedef sparse polynom<big int> poly; typedef poly::degree iterator degrees; poly S = “213*x^3443+532*x^4432-744*x^44-4235*x^15+292*x+34254”; cout << “S = ” << S << endl << endl; // Replace all degrees by their residues modulo 5 for(degrees di = S.degrees begin(), dj = S.degrees end(); di != dj; ++di) *di %= 5; // Now S can contain monomials this equal degrees // We have to reduce S to its canonical form S.normalize(); cout << “All degrees modulo 5 = ” << S << endl << endl; return 0;

slide-38
SLIDE 38

} S = 532*x^4432+213*x^3443-744*x^44-4235*x^15+292*x+34254 All degrees modulo 5 = -744*x^4+213*x^3+532*x^2+292*x+30019

slide-39
SLIDE 39

Example: matrix polynomial → polynomial matrix conversion

#include <arageli/arageli.hpp> // 3 −5 7

  • x8 +

1 −8

  • x3 +

−1 9 13 2

// 3x8 − 1 −5x8 + x3 + 9 13 7x8 − 8x3 + 2

  • using namespace std;

using namespace Arageli; int main(int argc, char *argv[ ]) { sparse polynom<matrix<int> > f = “(((3,-5),(0,7))*x^8+((0,1),(0,-8))*x^3+((-1,9),(13,2)))”; matrix<sparse polynom<int> > x = “((x,0),(0,x))”; cout << “f(x) = ” << f << endl << endl; cout << “Let x = ” << x << endl << endl;

slide-40
SLIDE 40

cout << “Then the resulting matrix is” << endl;

  • utput aligned(cout, f.subs(x));

return 0; } f(x) = ((3, -5), (0, 7))*x^8+((0, 1), (0, -8))*x^3+((-1, 9), (13, 2)) Let x = ((x, 0), (0, x)) Then the resulting matrix is || 3*x^8-1 -5*x^8+x^3+9 || || 13 7*x^8-8*x^3+2 ||

slide-41
SLIDE 41

5 Arageli’s (distinctive) characteristics

slide-42
SLIDE 42

5 Arageli’s (distinctive) characteristics

  • Support of mixed computations

All functions and operators that have more than one argument can take different types for similar arguments. For example, operator+ for two vectors can perform elementwise addition on vectors with different types of elements. There are several rules (that automatically verifies by a compiler) that define more precisely the meaning of similarity of argument types and allowable type propagation.

slide-43
SLIDE 43

5 Arageli’s (distinctive) characteristics

  • Support of mixed computations

All functions and operators that have more than one argument can take different types for similar arguments. For example, operator+ for two vectors can perform elementwise addition on vectors with different types of elements. There are several rules (that automatically verifies by a compiler) that define more precisely the meaning of similarity of argument types and allowable type propagation.

  • Intensive using of templated classes and functions.

This allows to use our code with user-defined classes.

slide-44
SLIDE 44

5 Arageli’s (distinctive) characteristics

  • Support of mixed computations

All functions and operators that have more than one argument can take different types for similar arguments. For example, operator+ for two vectors can perform elementwise addition on vectors with different types of elements. There are several rules (that automatically verifies by a compiler) that define more precisely the meaning of similarity of argument types and allowable type propagation.

  • Intensive using of templated classes and functions.

This allows to use our code with user-defined classes.

  • Conforming to C++ standard
slide-45
SLIDE 45

5 Arageli’s (distinctive) characteristics

  • Support of mixed computations

All functions and operators that have more than one argument can take different types for similar arguments. For example, operator+ for two vectors can perform elementwise addition on vectors with different types of elements. There are several rules (that automatically verifies by a compiler) that define more precisely the meaning of similarity of argument types and allowable type propagation.

  • Intensive using of templated classes and functions.

This allows to use our code with user-defined classes.

  • Conforming to C++ standard
  • Compilers:

– gcc 3.3.3, 4.0.4 – Microsoft Visual Studio C++ 2003, 2005 – Intel C++ 8.0, 9.0

slide-46
SLIDE 46

6 Comparison with other libraries

slide-47
SLIDE 47

6 Comparison with other libraries

  • NTL, Victor Shoup

“High-performance, portable C++ library providing data structures and algorithms for arbitrary length integers; for vectors, matrices, and polynomials over the integers and over finite fields; and for arbitrary precision floating point arithmetic”

slide-48
SLIDE 48

6 Comparison with other libraries

  • NTL, Victor Shoup

“High-performance, portable C++ library providing data structures and algorithms for arbitrary length integers; for vectors, matrices, and polynomials over the integers and over finite fields; and for arbitrary precision floating point arithmetic”

  • LiDIA, LiDiA Group, Technische Universit¨

at Darmstadt “A library for computational number theory”

slide-49
SLIDE 49

6 Comparison with other libraries

  • NTL, Victor Shoup

“High-performance, portable C++ library providing data structures and algorithms for arbitrary length integers; for vectors, matrices, and polynomials over the integers and over finite fields; and for arbitrary precision floating point arithmetic”

  • LiDIA, LiDiA Group, Technische Universit¨

at Darmstadt “A library for computational number theory” – kernel level (multiple precision integers, memory low-level routines) – interfaces level (standardaized functions for multiple precision integers and memory-managment functions) – simple (not parameterized) classes (bigrational, bigfloat,...) – parameterized classes (containers) (vector, matrix, power series, ...) – user inrefaces level (online documentation tool, interpreter)

slide-50
SLIDE 50

6 Comparison with other libraries

  • NTL, Victor Shoup

“High-performance, portable C++ library providing data structures and algorithms for arbitrary length integers; for vectors, matrices, and polynomials over the integers and over finite fields; and for arbitrary precision floating point arithmetic”

  • LiDIA, LiDiA Group, Technische Universit¨

at Darmstadt “A library for computational number theory” – kernel level (multiple precision integers, memory low-level routines) – interfaces level (standardaized functions for multiple precision integers and memory-managment functions) – simple (not parameterized) classes (bigrational, bigfloat,...) – parameterized classes (containers) (vector, matrix, power series, ...) – user inrefaces level (online documentation tool, interpreter)

  • CLN, Bruno Haible, Richard Kreckel

“a Class Library for Numbers”

slide-51
SLIDE 51

6 Comparison with other libraries

  • NTL, Victor Shoup

“High-performance, portable C++ library providing data structures and algorithms for arbitrary length integers; for vectors, matrices, and polynomials over the integers and over finite fields; and for arbitrary precision floating point arithmetic”

  • LiDIA, LiDiA Group, Technische Universit¨

at Darmstadt “A library for computational number theory” – kernel level (multiple precision integers, memory low-level routines) – interfaces level (standardaized functions for multiple precision integers and memory-managment functions) – simple (not parameterized) classes (bigrational, bigfloat,...) – parameterized classes (containers) (vector, matrix, power series, ...) – user inrefaces level (online documentation tool, interpreter)

  • CLN, Bruno Haible, Richard Kreckel

“a Class Library for Numbers”

  • GiNaC, GiNaC group, Johannes Gutenberg University, Mainz

“An open framework for symbolic computation within the C++ programming language”

slide-52
SLIDE 52

7 Arageli in action

slide-53
SLIDE 53

7 Arageli in action

New implementation of double description method

There are two possible description of a polyhedron P: P = {x ∈ Rd : Ax ≤ b}, where A ∈ Zm×d (1) P =

  • x ∈ Rd : x =

s

  • i=1

αiui +

n

  • i=1

βivi, ui ≥ 0, vi ≥ 0,

n

  • i=1

α = 1

  • (2)

(1) → (2) facet enumeration problem (2) → (1) vertex enumeration problem Double description method (DDM) [Motzkin, Raiffa, Thompson, Thrall, 1953] is one of the methods for solving problems (1) ↔ (2) cdd: implementation of DDM by Komei Fukuda [Fukuda, 1996] Skeleton 2: implementation of DDM [Zolotykh, 2006]. It implement a new variation of DDM and uses Arageli.

slide-54
SLIDE 54

Experimental results

Problem Input Output Time, sec m d p cdd Skeleton 2 cube18 18 36 262144 61 5 mit729-9 8 729 4862 55 6 prodmT62 24 3461 168 95 9 ccp7 21 64 116754 4760 61 ccc7 21 63 38780 1424 814 The experiment was performed on Intel Pentium D, Clock Speed 2.81GHz, L2cash 1Mb, 2Gb RAM. The program was compiled by C++ MS Visual Studio 2005 compiler with /o2 key. The test problems are from Fukuda’s repository.

slide-55
SLIDE 55

Web page

www.unn.ru/cs/arageli

Contacts

Sergey.Lyalin@itlab.unn.ru Zolotykh@vmk.unn.ru

slide-56
SLIDE 56
slide-57
SLIDE 57

That’s all, folks!