Міністерство освіти і науки України
Національний університет “Львівська політехніка”
Кафедра ЕОМ
Лабораторна робота №1
з дисципліни " Паралельні та розподілені обчислення"
на тему:
«ВИКОРИСТАННЯ ФУНКЦІОНАЛЬНОЇ ДЕКОМПОЗИЦІЇ
ДЛЯ РОЗВ’ЯЗКУ ОБЧИСЛЮВАЛЬНИХ ЗАДАЧ»
Мета: Вивчити методи декомпозицій задач. Набути навиків розв’язування задач з використанням функціональної декомпозиції.
Завдання для варіанту №20:
Вираз, який слід обрахувати, заданий наступним чином:
При чому елементи визначаються згідно правил:
, де bi=20/(i3+20) , і=1,2,...n
A1(20b1-c1)
A2C2- B 2, де Cij=20/(i3-j3+2)
Послідовність виконання.
1. Аналіз завдання.
Для заданого виразу вхідними даними є:
розмірність матриць – n;
матриці ;
вектори-стовпці .
Ці параметри повинні вводитися з клавіатури, або генеруватися випадковим чином (крім розмірності). При чому, елементи всіх матриць та векторів є цілими додатними числами, більшими за нуль.
Вектор-стовпець та матриця обраховуються, виходячи з уведеної розмірності, зауважимо, що значення їх елементів завжди менші одиниці і різко спадають зі збільшенням розмірності.
Наприклад для n=3, значення вектора-стовпця будуть становити: 20/(13 + 20) = 0,952; 20/(23 + 20) = 0,714 ; 20/(33 + 20) = 0,426, а значення матриці , відповідно:
20/(13-13+2) = 10 20/(13-23+2) = -4 20/(13-33+2) = -0,833
20/(23-13+2) = 2,22 20/(23-23+2) = 10 20/(23-33+2) = -1,176
20/(33-13+2) = 0,714 20/(33-23+2) = 0,952 20/(33-33+2) = 10
При утворенні враховуємо, що результатом множення матриці А на вектор-стовпець b є вектор-стовпець, елементи якого будуть раціональними числами(тобто матимуть значущу дробову частину).
При утворенні враховуємо, що результатом віднімання двох векторів-стовпців є вектор-стовпець, елементи якого можуть бути меншими за нуль цілими числами. Далі, при множенні цілочисельної додатної матриці А1 на результат віднімання, отримаємо вектор-стовпець з цілочисельними елементами довільного знаку.
При утворенні враховуємо, що присутні лише операції віднімання та множення, а тому вихідний результат може бути від'ємним і завжди матиме значущу дробову частину.
Таким чином, згідно поставленої задачі, в обчисленні загального виразу приймають участь три різні елементи – два вектори стовпці та матриця .
Перший доданок загального виразу містить чотири множники – транспонований вектор-стовпець у1, транспонований вектор-стовпець ,(тобто вектор-рядок), вектор-стовпець та матрицю . Оскільки, згідно правил матричних обчислень, добуток не є комутативною операцією, всі множення слід виконувати в тій послідовності, яка задана. Результатом множення рядка на стовпець є число, а матриці на матрицю - матриця. Тому, в загальному, перший доданок буде вектор-рядок. Аналогічний аналіз можна застосувати до всіх решти доданків даного виразу. Другий доданок - рядок х матриця = рядок, третій доданок – аналогічний другому. Остання дія - рядок х стовпець = число.
Таким чином, з попереднього випливає, що остаточний результат є число з дробовою частиною.
2. Декомпозиція задачі.
Однозначно, всі обчислення безпосередньо залежать від розмірності даних, тому найперше, слід забезпечити ввід змінної n, що визначає цю розмірність. Далі, можна паралельно виконувати обчислення значень вектора b та матриці С2, оскільки вони незалежні від інших параметрів. Крім того, на тому ж рівні декомпозиції слід визначати вхідні дані, тобто вводити з клавіатури, або генерувати випадковим чином матриці та вектори-стовпці . Наступний рівень декомпозиції – це знаходження елементів виразу. Значення залежить від введеної матриці А та обрахованого вектора b. Значення залежить від введеної А1 та різниці векторів b1 і c1, тому знайти його можна лише після обчислення А1 (20b1 - c1). Зауважимо, що множення на константу не є окремою операцією, як і транспонування векторів. Аналогічно, знаходимо . Подальша декомпозиція відбувається згідно заданої послідовності операцій та врахування залежностей отриманих на кожному рівні даних. Повна схема декомпозиції обчислення заданого виразу приведена нижче.
3. Об’єднання частин виразу проведено безпосередньо у схемі декомпозиції, оскільки воно однозначно визначається порядком обчислень.
4. Для написання програми, що ілюструє процес обчислення виразу згідно розробленої схеми декомпозиції, слід врахувати наступні особливості:
Дані, що вводяться з клавіатури, або генеруються випадковим чином повинні бути цілими числами, більшими за нуль. Результати проміжних обрахунків будуть містити дробову частину, виняток складає лише елемент y2. Тому слід обирати відповідний тип даних(багатобайтний).
Оскільки на окремо взятому рівні декомпозиції обраховуються незалежні частини підвиразів, функції що їх програмно реалізують повинні викликатися псевдо-одночасно.(Тобто перш ніж виконувати будь яку функцію третього рівня, слід виконати всі функції другого рівня і т.д.)
Для того, щоб результат загального виразу був співмірний з вхідними даними, слід нормувати отримані значення, визначивши тим самим порядок результату.
Схема декомпозиції обчислення виразу
5. Результат роботи програми
Рис. 1 Вікно програм
6. Висновки
В роботі використано паралелізм на рівні підзадач, оскільки передбачається, що кожен блок зі схеми декомпозиції є реалізований у виді функції. Це є середньоблоковий паралелізм. Обмін даними відбувається через використання спільних змінних. Присутня залежність даних між різними рівнями декомпозиції, але в межах одного рівня її немає. Є залежність за керуванням, оскільки послідовність обчислювального процесу наперед однозначно відома. Залежність за ресурсами та вводом/виводом може бути визначена лише у відношенні до певної обчислювальної системи.
Додаток А
Клас основного вікна програми Matrix.java:
(код не увесь, якщо потрібно увесь проект звертатись сюди l.petya@meta.ua)
public class Matrix extends javax.swing.JFrame {
public Matrix() {
initComponents();
}
int n = 0, maxRandomNumber = 10;
int[][] matrixA, matrixA1, matrixA2, matrixB2, vector_b1, vector_c1;
double[][] matrixC2, vector_b, y1, y2, Y3, result,
block_1_3, block_2_3, block_3_3,block_4_3,
block_1_4, block_2_4, block_1_5, x;
File file;
JFileChooser fileChooser = new javax.swing.JFileChooser();
double[][] writeInMass(double[][] k, JTable JT){
int m = k.length;
int n = k[0].length;
for(int i = 0; i < m; i++){
for(int c = 0; c<n; c++){
k[i][c] = Double.parseDouble(String.valueOf(JT.getValueAt(i, c)));
}
}
return k;
}
void writeMatrixInOutfield(int[][] m){
int c = m.length;
int n = m[0].length;
for(int i = 0; i < c; i++){
for(int c1 = 0; c1<n; c1++){
Output.append(m[i][c1] + "\t");
}
Output.append("\n");
}
}
void writeMatrixInOutfield(double[][] m){
int c = m.length;
int n = m[0].length;
for(int i = 0; i < c; i++){
for(int c1 = 0; c1<n; c1++){
Output.append(String.format("%.3f",m[i][c1] ) + "\t");
}
Output.append("\n");
}
}
int[][] writeInMass(int[][] k, JTable JT){
int m = k.length;
int n = k[0].length;
for(int i = 0; i < m; i++){
for(int c = 0; c<n; c++){
k[i][c] = Integer.parseInt(String.valueOf(JT.getValueAt(i, c)));
}
}
return k;
}
void initializationMatrixes(){
matrixA = new int[n][n];
matrixA1 = new int[n][n];
matrixA2 = new int[n][n];
matrixB2 = new int[n][n];
vector_b1 = new int[n][1];
vector_c1 = new int[n][1];
writeInMass(matrixA, JT_A);
writeInMass(matrixA1, JT_A1);
writeInMass(matrixA2, JT_A2);
writeInMass(matrixB2, JT_B2);
writeInMass(vector_b1, JT_b1);
writeInMass(vector_c1, JT_c1);
}
void writeInC2_and_b(){
n = Integer.parseInt(TF_n.getText());
matrixC2 = new double[n][n];
vector_b = new double[n][1];
for(int i = 0; i < n; i++){
for(int c = 0; c<n; c++){
JT_C2.setValueAt(String.format("%.3f", C2(i,c)), i, c);
matrixC2[i][c] = C2(i,c);
if(c==0){
JT_b.setValueAt(String.format("%.3f", f_y(i)), i, c);
vector_b[i][c] = f_y(i);
}
}}
}
double C2(int x, int y){
double i = x+1, j = y+1;
return 20/(i*i*i - j*j*j + 2);
}
double f_y(int x){
double i = x+1;
return 20/(i*i*i + 20);
}
double[][] func_y2(int[][] A1, int[][] b1, int[][] c1){
return MatrixMul(A1, MatrixSub(MulTheNumberOfMatrix(b1, 20), c1));
}
double[][] func_Y3(int[][] A2, double[][] C2, int[][] B2){
return MatrixSub(MatrixMul(A2, C2), B2);
}
double[][] func_block_1_3(double[][] y2, double[][] Y3){
return MulTheNumberOfMatrix(Y3, MatrixMul(transposition(y2),y2)[0][0]);
}
double[][] func_block_2_3(double[][] y2, double[][] Y3){
return MatrixMul(transposition(y2), exponentiation(Y3,3));
}
double[][] func_block_3_3(double[][] y2, double[][] Y3){
return MatrixMul(transposition(y2), Y3);
}
double[][] func_block_4_3(double[][] Y3, double[][] y1){
return MatrixMul(Y3, y1);
}
double[][] func_block_1_4(double[][] y1, double[][] block_1_3){
return MatrixMul(transposition(y1), block_1_3);
}
double[][] func_block_2_4(double[][] block_2_3, double[][] block_3_3){
return MatrixSum(block_2_3, block_3_3);
}
double[][] func_block_1_5(double[][] block_1_4, double[][] block_2_4){
return MatrixSum(block_1_4, block_2_4);
}
double[][] func_final_block(double[][] block_1_5, double[][] block_4_3){
return MatrixMul(block_1_5, block_4_3);
}
double[][] exponentiation(double[][] X, int exp){
double[][] res;
int k = exp;
res = MatrixMul(X,X);
k--;
while(k!=1){
res = MatrixMul(res,X);
k--;
}
return res;
}
double[][] MulTheNumberOfMatrix(double[][] b1, double num){
double[][] m;
m = new double[b1.length][b1[0].length];
for(int i = 0; i < m.length; i++){
for(int c1 = 0; c1<m[0].length; c1++){
m[i][c1] = b1[i][c1] * num;
}
}
return m;
}
double[][] transposition(double[][] matrix){
double[][] m;
m = new double[matrix[0].length][matrix.length];
for (int i = 0; i < matrix[0].length; i++) {
for (int j = 0; j < matrix.length; j++) {
m[i][j] = matrix[j][i];
}
}
return m;
}
void writeRandInTab(){
n = Integer.parseInt(TF_n.getText());
for(int i = 0; i < n; i++){
for(int c = 0; c<n; c++){
//k[i][c] = Double.parseDouble(String.valueOf(JT.getValueAt(i, c)));
JT_A.setValueAt(String.valueOf((short)(Math.random()*
(maxRandomNumber))+1), i, c);
JT_A1.setValueAt(String.valueOf((short)(Math.random()*
(maxRandomNumber))+1), i, c);
JT_A2.setValueAt(String.valueOf((short)(Math.random()*
(maxRandomNumber))+1), i, c);
JT_B2.setValueAt(String.valueOf((short)(Math.random()*
(maxRandomNumber))+1), i, c);
if(c==0){
JT_b1.setValueAt(String.valueOf((short)(Math.random()*
(maxRandomNumber))+1), i, c);
JT_c1.setValueAt(String.valueOf((short)(Math.random()*
(maxRandomNumber))+1), i, c);
}
}}
}
void writeTabs(){
n = Integer.parseInt(TF_n.getText());
JT_A.setModel(new javax.swing.table.DefaultTableModel(new Object [n][n], new String [n] ));
JT_A.setEnabled(true);
JT_A1.setModel(new javax.swing.table.DefaultTableModel(Object [n][n], new String [n] ));
JT_A1.setEnabled(true);
JT_A2.setModel(new javax.swing.table.DefaultTableModel(Object [n][n], new String [n] ));
JT_A2.setEnabled(true);
JT_B2.setModel(new javax.swing.table.DefaultTableModel(new Object [n][n], new String [n] ));
JT_B2.setEnabled(true);
JT_C2.setModel(new javax.swing.table.DefaultTableModel(new Object [n][n], String [n] ));
JT_C2.setEnabled(false);
JT_b.setModel(new javax.swing.table.DefaultTableModel(new Object [n][0], String [1] ));
JT_b.setEnabled(false);
JT_b1.setModel(new javax.swing.table.DefaultTableModel(new Object [n][0], new String [1] ));
JT_b1.setEnabled(true);
JT_c1.setModel(new javax.swing.table.DefaultTableModel(new Object [n][0], new String [1] ));
JT_c1.setEnabled(true);
}
double[][] MatrixMul(double[][] firstM, double[][] secondM){
double[][] resM = new double[firstM.length][secondM[0].length];
double temp = 0;
for(int m = 0; m < firstM.length; m++){
for(int n = 0; n < secondM[0].length; n++){
for(int c = 0; c < firstM[0].length; c++){
temp += firstM[m][c]*secondM[c][n];
}
resM[m][n] = temp;
temp = 0;
}
}
return resM;
}
double[][] MatrixSub(double[][] matrix1, double[][] matrix2) {
double[][] m;
m = new double[matrix1.length][matrix1[0].length];
for(int i = 0; i < matrix1.length; i++){
for(int c1 = 0; c1<matrix1[0].length; c1++){
m[i][c1] = matrix1[i][c1] - matrix2[i][c1];
}
}
return m;
}
double[][] MatrixSum(double[][] matrix1, double[][] matrix2) {
double[][] m;
m = new double[matrix1.length][matrix1[0].length];
for(int i = 0; i < matrix1.length; i++){
for(int c1 = 0; c1<matrix1[0].length; c1++){
m[i][c1] = matrix1[i][c1] + matrix2[i][c1];
}
}
return m;
}
void writeInFile(String str, File file){
String newLine = System.getProperty("line.separator");
try{
Writer filWriteStream=new FileWriter(file,true);
filWriteStream.write(newLine);
filWriteStream.write("----------------------start---------------------");
filWriteStream.write(newLine);
filWriteStream.write(str);
filWriteStream.write("-----------------------end---------------------");
filWriteStream.write(newLine);
filWriteStream.write(newLine);
filWriteStream.write(newLine);
filWriteStream.close();
} catch(Exception e){
javax.swing.JOptionPane.showMessageDialog(null,
"Помилка запису у файл \n"+file.getAbsolutePath());
}
}
private void JB_CalculateActionPerformed(java.awt.event.ActionEvent evt) {
initializationMatrixes();
Output.setText("");
Output.append("y1 = A x b:\n");
y1 = MatrixMul(matrixA, vector_b);
writeMatrixInOutfield(y1);
Output.append("------------------------------------------------\n");
Output.append("y2 = A1(20b1 - c1:\n \t20xb1 = \n");
writeMatrixInOutfield(MulTheNumberOfMatrix(vector_b1, 20));
Output.append("\n\t20xb1-c1 = \n");
writeMatrixInOutfield(MatrixSub(MulTheNumberOfMatrix(vector_b1, 20), vector_c1));
Output.append("\n\tA1(20b1 - c1)=\n");
y2 = func_y2(matrixA1, vector_b1, vector_c1);
writeMatrixInOutfield(y2);
Output.append("------------------------------------------------\n");
Output.append("Y3 = A2*C2 - B2:\n \tA2*C2 = \n");
writeMatrixInOutfield(MatrixMul(matrixA2, matrixC2));
Output.append("\n\tA2*C2 - B2 = \n");
Y3 = func_Y3(matrixA2, matrixC2, matrixB2);
writeMatrixInOutfield(Y3);
Output.append("------------------------------------------------\n");
Output.append("y2'y2*Y3:\n \ty2'y2 = \n");
writeMatrixInOutfield(MatrixMul(transposition(y2),y2));
Output.append("\n\ty2'y2*Y3 = \n");
block_1_3 = func_block_1_3(y2, Y3);
writeMatrixInOutfield(block_1_3);
Output.append("------------------------------------------------\n");
Output.append("y2'*Y3^3:\n \tY3^3 = \n");
writeMatrixInOutfield(exponentiation(Y3,3));
Output.append("\n\ty2'*Y3^3 = \n");
block_2_3 = func_block_2_3(y2, Y3);
writeMatrixInOutfield(block_2_3);
Output.append("------------------------------------------------\n");
Output.append("y2'*Y3 = \n");
block_3_3 = func_block_3_3(y2, Y3);
writeMatrixInOutfield(block_3_3);
Output.append("------------------------------------------------\n");
Output.append("Y3*y1 = \n");
block_4_3 = func_block_4_3(Y3, y1);
writeMatrixInOutfield(block_4_3);
Output.append("------------------------------------------------\n");
Output.append("y1'(y2'y2*Y3) = \n");
block_1_4 = func_block_1_4(y1, block_1_3);
writeMatrixInOutfield(block_1_4);
Output.append("------------------------------------------------\n");
Output.append("y2'*(Y3^3) + y2'*Y3 = \n");
block_2_4 = func_block_2_4(block_2_3, block_3_3);
writeMatrixInOutfield(block_2_4);
Output.append("------------------------------------------------\n");
Output.append("y1'(y2'y2*Y3) + y2'*(Y3^3) + y2'*Y3 = \n");
block_1_5 = func_block_1_5(block_1_4, block_2_4);
writeMatrixInOutfield(block_1_5);
Output.append("------------------------------------------------\n");
Output.append("(y1'(y2'y2*Y3) + y2'*(Y3^3) + y2'*Y3)*Y3*y1 = ");
x = func_final_block(block_1_5, block_4_3);
writeMatrixInOutfield(x);
Output.append("------------------------------------------------\n");
}
private void JB_RandomActionPerformed(java.awt.event.ActionEvent evt) {
maxRandomNumber = Integer.parseInt(jTextField1.getText());
writeTabs();
writeRandInTab();
writeInC2_and_b();
}
private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {
fileChooser.setName("Lab1_PRO.txt");
if(fileChooser.showOpenDialog(null)!=fileChooser.APPROVE_OPTION){
return;//Нажали Cancel
}
file = fileChooser.getSelectedFile();
writeInFile(Output.getText(), file);
}
Основний клас програми LAB1PRO.java:
public class LAB1PRO {
public static void main(String[] args) {
Matrix k = new Matrix();
k.setVisible(true);
k.setResizable(true);
k.setTitle("Matrix calc");
k.setLocationRelativeTo(null);
}
}