T u t o

advertisement
Tutorial 8
Topics
Matrix Methods
o The Matrix Class
o Matrices addition method
o Matrices multiplication method
Linear Systems
Queues and Stacks
o java.util library
o The Stack class
o Java collection framework
o Queue interface
Matrix Methods
In this section, we will discuss some of the Matrix class methods from the lecture.
The Matrix Class The Matrix class is a Java class we created to represent and
manipulate matrices. It is used most often to prepare matrices for use in solving linear
systems. It has:
§
A 2-D array with m rows by n columns
private double[ ][ ] data = new double[m][n];
int nrows = data.length;
int ncols = data[0].length;
§
Methods for matrix operations such as addition, subtraction, multiplication
Public Matrix addMatrices (Matrix b)
Public Matrix multMatrices (Matrix b)
Public void print ();
Matrix Addition
Two matrices (a & b) can be added only if they have the same number of rows and
columns. The result is a new matrix. The core of the addition process is:
c[i][j] = a[i][j] + b[i][j];
Here is the code
Public Matrix addMatrices (Matrix b)
{
//The result matix
Matrix result = new Matrix(nrows, ncols);
//Add only if they have the same number of rows and cols
if (b.nrows == nrows && b.ncols == ncols)
{
for (int i=0; i<nrows; i++)
for (int j=0; j<ncols; j++)
result.data[i][j] = data[i][j] + b.data[i][j];
}
return result;
}
Matrix Multiplication
Two matrices can be multiplied only if they have a.ncols = b.nrow. The result is a new
matrix. The core of the multiplication process is:
For example:
c[0][0] = a[0][0]* b[0][0] + a[0][1]*b[1][0] + a[0][2]*b[2][0] + …. +
a[0][ncols]*b[nrows][0];
Here is the code
Public Matrix multMatrices (Matrix b)
{
//The result matix has a.nrows by b.ncols
Matrix result = new Matrix(nrows, b.ncols);
//Multiply only if a.ncols = b.nrow
if (b.nrows == ncols)
{
for (int i=0; i<nrows; i++)
for (int j=0; j<b.ncols; j++)
for (int k=0; k<ncols; k++)
result.data[i][j]+= data[i][k] * b.data[k][j];
}
return result;
}
Linear Systems
Simultaneous equations arise in many engineering problems: they are a system of n
equations with n unknowns. Matrices are often used to solve linear systems. The
formulation is shown below:
AX=B
where A is the following matrix,
X = (x1, x2, ..., xn)
B = (b1, b2, ..., bn)'
For example: 2X0 + 3X1 + 5X2 = 10
X0 + 2X1 + 4X2 = 5
4X0 + 7X1 + 3X2 = 15
A is a 3 by 3 matrix: 2
3 5
1 2 4
4 7 3
X is a 3 by 1 matrix: X0
X1
X2
B is a 3 by 1 matrix: 10
5
15
The lecture notes walked you through the process of how we derived the Java
programs to solve a linear system. Here, we will show you how to use it. Basically,
there are three steps:
1. Create the left-side matrix a
2. Create the right-side matrix b
3. Plug a and b in the gaussian method of the Gauss class
Lets follow the steps to solve the above problem:
1.
Create the left-side matrix a
(To keep the code simple, we assume all arrays in the matrices are public)
Matrix a = new Matrix(3,3);
a.data[0][0] = 2.0;
a.data[0][1] = 3.0;
a.data[0][2] = 5.0;
a.data[1][0] = 1.0;
a.data[1][0] = 2.0;
a.data[1][2] = 4.0;
a.data[2][0] = 4.0;
a.data[2][1] = 7.0;
a.data[2][2] = 3.0;
2.
Create the right-side matrix b
Matrix b = new Matrix(3,1);
b.data[0][0] = 10.0;
b.data[1][0] = 5.0;
b.data[2][0] = 15.0;
3.
Plug a and b in the gaussian method of the Gauss class
Matrix result = new Matrix(3,1);
GaussMain.gaussian (a, b, result);
//Print the solution
result.print();
Here is the result
X0 = 6.0
X1 = -1.5
X2 = 0.5
As you can see, solving a linear system using the Gauss class is incredibly simple. If you
are interested in learning about how we derived the gaussian method, please see the
appendix
Queues and Stacks
A data structure is a systematic way of organizing and accessing data; we have already
seen a number of simple data structures in this course (e.g., arrays and vectors). This
section (and the next tutorial) will show you how to implement some of the traditional
data structures (Queue, Stack, Linked List, and Tree) using Java.
java.util Library
Before the release of the Java 2 platform, the java.util library supplied a small set of
classes for the most useful data structures, such as Vector, Stack, and Hashtable:
The Vector class implements a growable array of objects. Like an array, it
contains components that can be accessed using an integer index. However,
the size of a Vector can grow or shrink as needed to accommodate adding and
removing items after the Vector has been created.
The Stack class represents a last-in-first-out (LIFO) stack of objects. It provides
a push method to add an object at the top of the stack and a pop method to
remove it from the top.
The Hashtable class stores objects as a key-value pairs which can be randomly
accessed using the key.
Stack Class
A stack is a container of objects that are inserted and removed according to the last-in
first-out (LIFO) principle. An example of this principle is a can of tennis balls. The
last ball inserted in the can is the first one that will be taken out. The java.util.Stack
class contains the following methods:
void push(Object item)
pushes an item onto the stack. Parameters: item the item to be added
Object pop()
pops and returns the top item of the stack. Don't call this method if the stack is
empty.
Object peek()
returns the top of the stack without popping it. Don't call this method if the
stack is empty.
In the following example, we simulate the tennis ball can using two classes: TennisBall
and TennisBallCan. First, lets define a simple TennisBall class which contains only 1
attribute: color.
class TennisBall{
String color;
TennisBall (String color){
this.color = color;
}
}
String getColor() {
return color;
}
Next, let's define the TennisBallCan class which uses a Stack to organize its balls.
import java.util.*;
import TennisBall; class TennisBallCan {
public static void main (String args[]) {
//Create 3 objects of TennisBall
TennisBall t1 = new TennisBall ("Red") ;
TennisBall t2 = new TennisBall ("Green");
TennisBall t3 = new TennisBall ("Yellow")
Stack can = new Stack();
//Push the balls into the can
System.out.println
can.push (t1);
System.out.println
can.push (t2) ;
System.out.println
can.push (t3);
System.out.println
(t1.getColor() + " ball in");
(t2.getColor() + " ball in");
(t3.getColor() + " ball in");
("Size of the can: " + can.size());
//Take a peek of the last ball
System.out.println ("Peek of the last ball: color = " +
((TennisBall)can.peek()).getColor());
System.out.println ("Size of the can after the peek: " + can.size());
//Pop the balls
for (int i=0; i<3; i++)
System.out.println (((TennisBall)can.pop()).getColor() + " ball out" );
}
}
Here is the result
Red ball in
Green ball in
Yellow ball in
Size of the can: 3
Peek of the last ball:Yellow
Size of the can after the peek: 3
Yellow ball out
Green ball out
Red ball out
Size of the can after the pop: 0
The Java Collections Framework
Introduced with the JavaTM 2 platform, the Java Collections Framework provides a
well-designed set of interfaces and classes for storing and manipulating groups of data
as a single unit - a collection. The framework provides a convenient API to many of the
abstract data types: maps, sets, lists, trees, arrays, hashtables and other collections.
Because of their object-oriented design, the Java classes in the Collections Framework
encapsulate both the data structures and the algorithms associated with these
abstractions.
As is common for modern data structure libraries, the Java collection library separates
interfaces and implementations. Next, we will look at that separation with a familiar
data structure, the queue. The Java library does not supply a queue class or interface,
but it is nevertheless a good example to introduce the basic concepts.
Queue Interface
A queue interface specifies that you can add elements at the tail end of the queue,
remove them at the head, and find out how many elements are in the queue. You use
a queue when you need to collect objects and retrieve them in a "first in, first out"
fashion.
The queue interface should perform the following operations:
interface Queue{
void add(Object obj);
Object remove();
int size();
}
Note that the interface tells you nothing about how the queue is implemented. Here is
an example of how one can implement the Queue interface:
class TennisBallQueue implements Queue {
public void add(Object obj) { . . . }
public Object remove() { . . . }
public int size() { . . . }
}
NOTE: If you do need a queue, you can simply use the LinkedList class in java.util
library. Among other methods, LinkedList provides the following "queue-like"
operations:
void addLast(Object o)
Appends the given element to the end of this list.
Object removeFirst()
Removes and returns the first element from this list.
We will discuss LinkedList next week.
4) Tutorial Problems 1. Matrix Methods
Here are three matrices: A, B, and C
1 2 3
A= 5 6 7
9 4 5
3 2 4
B= 2 1 6
4 10 20
3
C= 5
6
What is the result of (A-B)*C
2. Linear Systems
Solve the following linear system for X, Y, and Z.
X+Y+Z=8
X+Y-Z=4
X-Y=4
3. Stack
I modified the TennisBallCan example and added the following actions in my program:
Create an empty can
Move all balls from one can to another
Balls in the new can should have the reverse order of those in the original can
5) Appendix: Simultaneous Linear Equations
Simultaneous equations arise in many engineering problems: a system of n equations
with n unknowns. The matrix formulation of of these linear systems is shown below:
AX=B,
where A is the following matrix,
and X = (x1, x2, ..., xn)', B = (b1, b2, ..., bn)'
The basic steps in solving simultaneous equations are the following.
Triangularization
The set of equations need to be converted a form so that only the upper triangular
element remains. This process is called triangularization.The triangularized set of
equations is shown below.
a11 * x1 + a12 * x2 + a13 * x3 +.... + a1n * xn = b1
0 * x1 + a'22 * x2 + a'23 * x3 + .... + a'2n * xn = b'2
0 * x1 + 0 * x2 + a'33 * x3 +.... + a'3n * xn = b'3
.......
0 * x1 + 0 * x2 + 0 * x3 +.... + a'nn * xn = b'n
The idea behind triangularization is very simple. We know that if we multiply both
sides of an equation, the equation remains the same. Our aim is to make the elements
below the diagonal to be zero. So if we start with the first column then we need to
make all the elements except the first element equal zero. Also we do not want to
change the equations. Lets consider the bottom row first, if we multiply the bottom
row with a11 and then divide by an1 and then subtract from this row the first row we
have made the first element equal to zero. We do this for all the columns and rows
until we get the triangular matrix. The code is given below.
private static void forward_solve(Matrix q)
{
int i, j, k, maxr, n;
double t, pivot;
n= q.getNumRows();
for (i=0; i < n; i++) { // Find row w/max element in this
maxr= i; // column, at or below diagonal
for (j= i+1; j < n; j++)
if (Math.abs(q.getElement(j,i)) > Math.abs(q.getElement(maxr,i)))
maxr= j;
if (maxr != i) // If row not current row, swap
for (k=i; k <= n; k++)
{ t= q.getElement(i,k); // t= q(i,k)
q.setElement(i,k, q.getElement(maxr, k)); // q(i,k)= q(maxr, k)
q.setElement(maxr, k, t); // q(maxr, k)= t
}
for (j= i+1; j <n; j++) // Calculate pivot ratio
{ pivot= q.getElement(j,i)/q.getElement(i,i); // q(j,i)/q(i,i)
for (k= n; k >=i; k--)
q.setElement(j, k, q.getElement(j,k)-q.getElement(i,k)*pivot);
// q(j,k) -= q(i,k)*pivot; // Update row j below diag
}
}
}
Back-substitution
Once the triangular matrix is obtained the solution is obtained by a process known as
back-substitution. We start from the bottom most row. Since the matrix is triangular
we have only one non zero element in the bottom most row. So the value of xn can be
readly obtained, xn can be computed as b'n/a'nn, then xn-1 = ( b'n-1 - a'n-1,n * xn ) /
a'n-1,n-1. And so on to x1. The code for backsubstitution is given below:
private static void back_solve(Matrix q) // Back substitution function
{ // starting at row n-1
int j, k, n;
double t; // t- temporary
n= q.getNumRows();
for (j=n-1; j >=0; j--) // Start at last row
{
t= 0.0;
for (k= j+1; k < n; k++) // t += q(j,k)* q(k,n)
t += q.getElement(j,k)* q.getElement(k,n);
q.setElement(j, n, (q.getElement(j, n) -t)/q.getElement(j,j));
// q(j, n)= (q(j, n) -t)/q(j,j);
}
}
Partial-pivoting implementation of Gaussian elimination
The implementation gathers up all we have been saying so far:
public static void gaussian(Matrix a, Matrix b, Matrix x) {
int i, j, n;
n= a.getNumRows(); // Number of unknowns
Matrix q= new Matrix(n, n+1);
for (i=0; i < n; i++) {
for (j=0; j < n; j++) // Form q matrix
q.setElement(i, j, a.getElement(i, j)); // q(i,j)= a(i,j)
q.setElement(i, n, b.getElement(i, 0)); // q(i,n)= b(i,0)
}
forward_solve(q); // Do Gaussian elimination
back_solve(q); // Perform back substitution
}
for (i=0; i<n; i++)
x.setElement(i, 0, q.getElement(i, n)); // x(i,0)= q(i,n)
We can make this method part of the Matrix class.
Download