Численный метод Якоби. С Matlab на C#
Формулировка задачи:
помогите пожалуйста с методом Якобы, чтобы на экран выводил только ответы , программа написано в матлабе
clear all
clc
n=input('количество строк (n): ');
A=input('вводить матрицу A: ');
b=input('ввдоить матрицу b, вектор столбец: ');
m=input('максимальное число итераций (m): ');
E=input('допустимая погрешность (стандартного значения): ');
X0=zeros(1,n);
X=X0;
K=0;
Norma=1;
while Norma>E
K=K+1;
fprintf ('%d',K);
for i=1:n
suma=0;
for j=1:n
if j~=i
suma=suma+A(i,j)*X(j);
end
end
X(i)=(b(i)-suma)/A(i,j);
fprintf('%10.6f',X(i));
end
Norma=norm(X0-X);
fprintf('%10.6f\n',Norma);
X0=X;
if K>=m
break
end
end
а вот и матрица {3 -2 1 5
2 1 -1 4
1 -5 3 0}
Решение задачи: «Численный метод Якоби. С Matlab на C#»
textual
Листинг программы
using System;
using System.Threading;
//-------------------------------------------
// Simple Iterations Classes.
// Seidel and Jacobi.
// Grinchenko University. Informatics, 2-nd course.
// Kudinov Ruslan
// (c) 2014
//-------------------------------------------
namespace app
{
class Application
{
// Entry point
// Точка входа.
static void Main(string[] args)
{
// m m m | a
// m m m | a
// m m m | a
// Matrix coefficients
// Матрица коеффциентов СЛАУ
double[,] matrix = new double[3, 3] {
{ 4, 0.24, -0.08},
{ 0.09, 3, -0.15},
{ 0.04, -0.08, 4}
};
// matrix of free coefficients
// матрица свободных членов
double[] additional = new double[3] {
8,
9,
20
};
// Enter values by user
// Ввод значений вручную.
// matrix = setVal(matrix);
// additional = setVal(additional);
// Create and init.
// Объявляем и инициализимруем классы.
Seidel i = new Seidel(matrix, additional, 0.0001);
Jacobi j = new Jacobi(matrix, additional, 0.0001);
// set method args of ThreadStart delegate
// Передаем методы потоку через делегат ThreadStart
Thread Z = new Thread(new ThreadStart(i.calculateMatrix));
Thread Y = new Thread(new ThreadStart(j.calculateMatrix));
// Start threads
// Запускаем потоки.
Z.Start();
Y.Start();
// wait for endings
// Ожидаем завершения.
Z.Join();
Y.Join();
// Show results of calculations
// Выводим на экран.
Console.WriteLine("\n Seidel method:");
showMatrix(i.ResultMatrix);
Console.WriteLine("\n Jakobi method:");
showMatrix(j.ResultMatrix);
Console.ReadKey();
}
//------------------------------------------
// setVal - method of array values enter overloads
// setVal - Перегрузки методов ввода значений для
// матрицы коеффициентов и свободных членов.
//------------------------------------------
static double[,] setVal(double[,] x)
{
Console.WriteLine("\n Matrix cofficients:");
for (int i = 0; i < x.GetLength(0); i++)
{
for (int j = 0; j < x.GetLength(1); j++)
{
Console.Write("Enter value of {0}{1}: ", i, j);
x[i, j] = Convert.ToDouble(Console.ReadLine());
}
}
return x;
}
static double[] setVal(double[] x)
{
Console.WriteLine("\n Addtional matrix values:");
for (int i = 0; i < x.Length; i++)
{
Console.Write("Enter value of {0}: ", i);
x[i] = Convert.ToDouble(Console.ReadLine());
}
return x;
}
//------------------------------------------
// showMatrix - method overloads showing results
// showMatrix - перегрузки разнотипных выводов
//------------------------------------------
static void showMatrix(double[,] x)
{
Console.WriteLine("\n Result:");
for (int i = 0; i < x.GetLength(0); i++)
{
for (int j = 0; j < x.GetLength(1); j++)
{
Console.Write(" {0} ", x[i, j]);
}
Console.WriteLine();
}
}
static void showMatrix(double[] x)
{
Console.WriteLine("\n Result:");
for (int i = 0; i < x.Length; i++)
{
Console.WriteLine(" {0} ", x[i]);
}
}
}
// Base class of all iteration methods
// Общий класс для итерационных методов.
abstract class SimpleIterations
{
public abstract void calculateMatrix();
}
/// <summary>
/// Class Jacobi
/// Класс отвечает за работу метода Якоби
/// </summary>
class Jacobi : SimpleIterations
{
// Матрица ответов
private double[] resultMatrix;
public double[] ResultMatrix
{
get
{
if (resultMatrix != null)
return resultMatrix;
else
{
return new double[3] { 0, 0, 0 };
}
}
}
// Основная матрица и свободные члены.
private double[,] matrix;
private double[] addtional;
// точность (кол-во итераций)
private double accuracy;
// избегаем ошибок с итерациями.
public double Accuracy
{
get
{
return accuracy;
}
set
{
if (value <= 0.0)
accuracy = 0.1;
else
accuracy = value;
}
}
// Конструктор. Получает значения при создании.
public Jacobi(double[,] Matrix, double[] FreeElements, double Accuracy)
{
this.matrix = Matrix;
this.addtional = FreeElements;
this.Accuracy = Accuracy;
}
// Сам метод рассчета.
public override void calculateMatrix()
{
// общий вид:
// [x1] [ b1/a11 ] / 0 x x \
// [x2] = [ b2/a22 ] - | x 0 x |
// [x3] [ b3/a33 ] \ x x 0 /
// где x - делится на диагональый элемент первоначальной матрицы.
// где b - эелементы из свободных членов
// где а - элементы из матрицы
// матрица коеффициентов + столбец свободных членов.
double[,] a = new double[matrix.GetLength(0), matrix.GetLength(1) + 1];
for (int i = 0; i < a.GetLength(0); i++)
for (int j = 0; j < a.GetLength(1) - 1; j++)
a[i, j] = matrix[i, j];
for (int i = 0; i < a.GetLength(0); i++)
a[i, a.GetLength(1) - 1] = addtional[i];
//---------------
// Метод Якоби.
//---------------
// Введем вектор значений неизвестных на предыдущей итерации,
// размер которого равен числу строк в матрице, т.е. size,
// причем согласно методу изначально заполняем его нулями
double[] previousValues = new double[a.GetLength(0)];
for (int i = 0; i < a.GetLength(0); i++)
{
previousValues[i] = 0.0;
}
// Будем выполнять итерационный процесс до тех пор,
// пока не будет достигнута необходимая точность
while (true)
{
// Введем вектор значений неизвестных на текущем шаге
double[] currentValues = new double[a.GetLength(0)];
// Посчитаем значения неизвестных на текущей итерации
// в соответствии с теоретическими формулами
for (int i = 0; i < a.GetLength(0); i++)
{
// Инициализируем i-ую неизвестную значением
// свободного члена i-ой строки матрицы
currentValues[i] = a[i, a.GetLength(0)];
// Вычитаем сумму по всем отличным от i-ой неизвестным
for (int j = 0; j < a.GetLength(0); j++)
{
if (i != j)
{
currentValues[i] -= a[i, j] * previousValues[j];
}
}
// Делим на коэффициент при i-ой неизвестной
currentValues[i] /= a[i, i];
}
// Посчитаем текущую погрешность относительно предыдущей итерации
double differency = 0.0;
for (int i = 0; i < a.GetLength(0); i++)
differency += Math.Abs(currentValues[i] - previousValues[i]);
// Если необходимая точность достигнута, то завершаем процесс
if (differency < accuracy)
break;
// Переходим к следующей итерации, так
// что текущие значения неизвестных
// становятся значениями на предыдущей итерации
previousValues = currentValues;
}
resultMatrix = previousValues;
}
}
/// <summary>
/// Класс Отвечает за работу метода Зейделя.
/// Class Seidel
/// </summary>
class Seidel : SimpleIterations
{
// Матрица ответов
private double[] resultMatrix;
public double[] ResultMatrix
{
get
{
if (resultMatrix != null)
return resultMatrix;
else
{
return new double[3] { 0, 0, 0 };
}
}
}
// private int t;
// Основная матрица и свободные члены.
private double[,] matrix;
private double[] addtional;
// точность (кол-во итераций)
private double accuracy;
// избегаем ошибок с итерациями.
public double Accuracy
{
get
{
return accuracy;
}
set
{
if (value <= 0.0)
accuracy = 0.1;
else
accuracy = value;
}
}
// Конструктор. Получает значения при создании.
public Seidel(double[,] Matrix, double[] FreeElements, double Accuracy)
{
this.matrix = Matrix;
this.addtional = FreeElements;
this.Accuracy = Accuracy;
}
// Сам метод рассчета.
public override void calculateMatrix()
{
// общий вид:
// [x1] [ b1/a11 ] / 0 x x \
// [x2] = [ b2/a22 ] - | x 0 x |
// [x3] [ b3/a33 ] \ x x 0 /
// где x - делится на диагональый элемент первоначальной матрицы.
// где b - эелементы из свободных членов
// где а - элементы из матрицы
// матрица коеффициентов + столбец свободных членов.
double[,] a = new double[matrix.GetLength(0), matrix.GetLength(1) + 1];
for (int i = 0; i < a.GetLength(0); i++)
for (int j = 0; j < a.GetLength(1) - 1; j++)
a[i, j] = matrix[i, j];
for (int i = 0; i < a.GetLength(0); i++)
a[i, a.GetLength(1) - 1] = addtional[i];
//---------------
// Метод Зейделя.
//---------------
// Введем вектор значений неизвестных на предыдущей итерации,
// размер которого равен числу строк в матрице, т.е. size,
// причем согласно методу изначально заполняем его нулями
double[] previousValues = new double[matrix.GetLength(0)];
for (int i = 0; i < previousValues.GetLength(0); i++)
{
previousValues[i] = 0.0;
}
// Будем выполнять итерационный процесс до тех пор,
// пока не будет достигнута необходимая точность
while (true)
{
// Введем вектор значений неизвестных на текущем шаге
double[] currentValues = new double[a.GetLength(0)];
// Посчитаем значения неизвестных на текущей итерации
// в соответствии с теоретическими формулами
for (int i = 0; i < matrix.GetLength(0); i++)
{
// Инициализируем i-ую неизвестную значением
// свободного члена i-ой строки матрицы
currentValues[i] = a[i, a.GetLength(0)];
// Вычитаем сумму по всем отличным от i-ой неизвестным
for (int j = 0; j < a.GetLength(0); j++)
{
// При j < i можем использовать уже посчитанные
// на этой итерации значения неизвестных
if (j < i)
{
currentValues[i] -= a[i, j] * currentValues[j];
}
// При j > i используем значения с прошлой итерации
if (j > i)
{
currentValues[i] -= a[i, j] * previousValues[j];
}
}
// Делим на коэффициент при i-ой неизвестной
currentValues[i] /= a[i, i];
}
// Посчитаем текущую погрешность относительно предыдущей итерации
double differency = 0.0;
for (int i = 0; i < a.GetLength(0); i++)
differency += Math.Abs(currentValues[i] - previousValues[i]);
// Если необходимая точность достигнута, то завершаем процесс
if (differency < accuracy)
break;
// Переходим к следующей итерации, так
// что текущие значения неизвестных
// становятся значениями на предыдущей итерации
previousValues = currentValues;
}
// результат присваиваем матрице результатов.
resultMatrix = previousValues;
}
}
}