//---------------------------------------------------------------------------
#include <vcl.h>
#include <time.h>
#include <math.h>
#include <stdio.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
int n,m;
float epsilon; //Точность
double**a; //Матрица
double *f; //Столбец правых частей
double *x; //Решение
double *ax;
double**b;
bool ch=0;
double *tm;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
sg[0]=StringGrid2;
sg[1]=StringGrid3;
sg[2]=StringGrid4;
sg[3]=StringGrid5;
sg[4]=StringGrid6;
sg[5]=StringGrid7;
sg[6]=StringGrid8;
}
//---------------------------------------------------------------------------
//Матрично-векторное умножение
void mv_mult(double **a,double *x, double *ax)
{
for (int i=0;i<n;i++)
{
ax[i]=0;
for (int j=0;j<n;j++)
{
ax[i]+=a[i][j]*x[j];
}
}
}
//---------------------------------------------------------------------------
//Векторное вычитание
void vv_substr(double *ax, double *f, double *r)
{
for (int i=0;i<n;i++)
{
r[i]=ax[i]-f[i];
}
}
//---------------------------------------------------------------------------
//Векторное сложение
void vv_addit(double *ax, double *f, double *r)
{
for (int i=0;i<n;i++)
{
r[i]=ax[i]+f[i];
}
}
//---------------------------------------------------------------------------
//Норма вектора
double norma(double * vec)
{
double nr=0;
for (int i=0;i<n;i++)
{
nr+=vec[i]*vec[i];
}
return (sqrt(nr));
}
//---------------------------------------------------------------------------
//Скалярное умножение векторов
double vv_mult(double *a,double *x)
{
double ax=0;
for (int i=0;i<n;i++)
{
ax+=a[i]*x[i];
}
return(ax);
}
//---------------------------------------------------------------------------
//Проверка на заданную точность нормы
bool check(double *a)
{
double mod;
mod=norma(a);
if (mod<epsilon) return(1);
else return(0);
}
//---------------------------------------------------------------------------
//Построение матрицы B для метода минимальных поправок
void mkB()
{
ch=1;
b=new double* [n];
for (int i=0; i<n; i++)
{
b[i]=new double[n];
for (int j=0; j<n; j++)
if (i!=j) b[i][j]=0;
else b[i][j]=a[i][j]-300;
}
}
//---------------------------------------------------------------------------
//Заполнение матрицы
void __fastcall TForm1::Button5Click(TObject *Sender)
{
Button1->Enabled=true;
Button2->Enabled=true;
Button3->Enabled=true;
Button4->Enabled=true;
CheckBox2->Enabled=true;
time_t t;
time(&t); srand((unsigned)t);
n=StrToInt(Edit1->Text);
m=StrToInt(Edit3->Text);
epsilon=StrToFloat(Edit2->Text);
StringGrid1->ColCount=n;
StringGrid1->RowCount=n;
for (int i=0;i<6;i++)
sg[i]->RowCount=n;
f=new double [n];
if (CheckBox2->Checked==false){
a=new double* [n];
tm=new double [n];
x=new double [n];
for (int i=0;i<n;i++)
a[i]=new double [n];
for (int i=0;i<n;i++)
{
double b=rand()%200-100;
double c=rand()%100+1;
x[i]=b/c;
sg[1]->Cells[0][i]=FloatToStr(x[i]);
for (int j=0;j<=i;j++)
{
double b=rand()%200-100;
double c=rand()%100+1;
a[i][j]=b/c;
a[j][i]=a[i][j];
if ((i==j)&&(CheckBox1->Checked==true)) a[i][j]+=m;
if (i==j) tm[i]=a[i][j];
StringGrid1->Cells[j][i]=FloatToStr(a[i][j]);
StringGrid1->Cells[i][j]=FloatToStr(a[j][i]);
}
}}
else
for (int i=0;i<n;i++)
{
a[i][i]=tm[i]+(double)m;
tm[i]+=m;
StringGrid1->Cells[i][i]=FloatToStr(a[i][i]);
StringGrid1->Cells[i][i]=FloatToStr(a[i][i]);
}
mv_mult(a,x,f);
for(int i=0;i<n;i++)
sg[0]->Cells[0][i]=FloatToStr(f[i]);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
for (int i=0;i<n;i++)
{
delete [] a[i];
if (ch==1) delete [] b[i];
}
}
//---------------------------------------------------------------------------
//Метод минимальных невязок
void __fastcall TForm1::Button1Click(TObject *Sender)
{
double *rk; //невязка
double *t; //вспомогательный вектор
double *xk;
double *xk1;
double tau,sm,nrm;
ax=new double [n];
xk=new double [n];
xk1=new double [n];
rk=new double [n];
t=new double [n];
for (int i=0;i<n;i++)//Задаём начальное приближение
xk[i]=0;
int k=0;
mv_mult(a,xk,ax); //ax=A*xk
vv_substr(ax,f,rk); //Вычисляем невязку: rk=A*xk-f
bool c=check(rk);
while (c==0)
{
mv_mult(a,rk,ax); //A*rk
sm=vv_mult(ax,rk); //Считаем скалярное произведение: (A*rk,rk)
nrm=norma(ax);
tau=sm/(nrm*nrm);
for (int i=0;i<n;i++)
{
t[i]=rk[i]*tau;
ax[i]=ax[i]*tau;
}
vv_substr(xk,t,xk1);
for (int i=0;i<n;i++)
{
xk[i]=xk1[i];
}
vv_substr(rk,ax,t);
for (int i=0;i<n;i++)
{
rk[i]=t[i];
}
c=check(rk);k++;
}
for(int i=0;i<n;i++)
sg[2]->Cells[0][i]=FloatToStr(xk[i]);
sg[6]->Cells[0][0]="Метод мин.невязок";
sg[6]->Cells[1][0]=IntToStr(k);;
delete []rk; delete [] xk; delete []xk1; delete [] t;
}
//---------------------------------------------------------------------------
//Метод минимальных поправок
void __fastcall TForm1::Button2Click(TObject *Sender)
{
double *rk; //невязка
double *wk; //поправка
double *vk;
double *xk;
double *xk1;
double *t;
double tau,sm,smd;
ax=new double [n];
xk=new double [n];
xk1=new double [n];
rk=new double [n];
wk=new double [n];
vk=new double [n];
t=new double [n];
for (int i=0;i<n;i++)//Задаём начальное приближение
xk[i]=0;
bool c=0;
mkB();int k=0;
mv_mult(a,xk,ax); //ax=A*xk
vv_substr(ax,f,rk); //Вычисляем невязку: rk=A*xk-f
mv_mult(b,rk,wk); //Вычисляем поправку wk=B*rk
while (c==0)
{
mv_mult(a,wk,ax); //ax=A*wk
mv_mult(b,ax,vk); //vk=B*A*wk
sm=vv_mult(ax,wk); //Считаем скалярное произведение: (A*wk,wk)
smd=vv_mult(vk,ax);
tau=sm/smd;
for (int i=0;i<n;i++)
t[i]=wk[i]*tau;
vv_substr(xk,t,xk1);
for (int i=0;i<n;i++)
{
xk[i]=xk1[i];
vk[i]=vk[i]*tau;
}
vv_substr(wk,vk,t);
for (int i=0;i<n;i++)
{
wk[i]=t[i];
}
c=check(wk);k++;
}
for(int i=0;i<n;i++)
sg[3]->Cells[0][i]=FloatToStr(xk[i]);
sg[6]->Cells[0][1]="Метод мин.поправок";
sg[6]->Cells[1][1]=IntToStr(k);
delete []rk; delete [] xk; delete []xk1;delete []wk; delete [] vk; delete [] t;
}
//---------------------------------------------------------------------------
//Метод скорейшего спуска
void __fastcall TForm1::Button3Click(TObject *Sender)
{
double *rk; //невязка
double *xk;
double *xk1;
double *t;
double tau,sm,smd;
ax=new double [n];
xk=new double [n];
xk1=new double [n];
rk=new double [n];
t=new double [n];
for (int i=0;i<n;i++)//Задаём начальное приближение
xk[i]=0;
bool c=0;
int k=0;
mv_mult(a,xk,ax); //ax=A*xk
vv_substr(ax,f,rk); //Вычисляем невязку: rk=A*xk-f
while (c==0)
{
mv_mult(a,rk,ax); //A*rk
sm=vv_mult(rk,rk); //Считаем скалярное произведение: (rk,rk)
smd=vv_mult(ax,rk); //Считаем скалярное произведение: (A*rk,rk)
tau=sm/smd;
for (int i=0;i<n;i++)
{
t[i]=rk[i]*tau;
ax[i]=ax[i]*tau;
}
vv_substr(xk,t,xk1);
for (int i=0;i<n;i++)
xk[i]=xk1[i];
vv_substr(rk,ax,t);
for (int i=0;i<n;i++)
{
rk[i]=t[i];
}
c=check(rk);k++;
}
for(int i=0;i<n;i++)
sg[4]->Cells[0][i]=FloatToStr(xk[i]);
sg[6]->Cells[0][2]="Метод наиск.спуска";
sg[6]->Cells[1][2]=IntToStr(k);
delete []rk; delete [] xk; delete []xk1;
}
//---------------------------------------------------------------------------
//Метод сопряженных градиентов
void __fastcall TForm1::Button4Click(TObject *Sender)
{
double *rk; //невязка
double *rk1;
double *pk;
double *xk;
double *xk1;
double *t;
double alpha,beta,sm,smd;
ax=new double [n];
xk=new double [n];
xk1=new double [n];
rk=new double [n];
rk1=new double [n];
pk=new double [n];
t=new double [n];
for (int i=0;i<n;i++)//Задаём начальное приближение
xk[i]=0;
bool c=0;
int k=0;
mv_mult(a,xk,ax); //ax=A*xk
vv_substr(ax,f,rk); //Вычисляем невязку: r0=A*x0-f
vv_substr(ax,f,pk); //p0=r0
while (c==0)
{
mv_mult(a,pk,ax); //A*pk
sm=vv_mult(rk,rk); //Считаем скалярное произведение: (rk,rk)
smd=vv_mult(ax,pk); //Считаем скалярное произведение: (A*pk,pk)
alpha=sm/smd;
for (int i=0;i<n;i++)
{
t[i]=pk[i]*alpha;
ax[i]=ax[i]*alpha;
}
vv_addit(xk,t,xk1);
for (int i=0;i<n;i++)
xk[i]=xk1[i];
vv_substr(rk,ax,rk1);
sm=vv_mult(rk1,rk1);
smd=vv_mult(rk,rk);
beta=sm/smd;
c=check(rk);
for (int i=0;i<n;i++)
pk[i]=pk[i]*beta;
vv_addit(rk1,pk,pk);
for (int i=0;i<n;i++)
rk[i]=rk1[i];
k++;
}
for(int i=0;i<n;i++)
{
xk[i]=-1*xk[i];
sg[5]->Cells[0][i]=FloatToStr(xk[i]);
}
sg[6]->Cells[0][3]="Метод сопр.градиентов";
sg[6]->Cells[1][3]=IntToStr(k);
delete []rk; delete [] xk; delete []xk1;delete []rk1; delete [] pk;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Edit1Change(TObject *Sender)
{
CheckBox2->Enabled=false;
CheckBox2->Checked=false;
}
//---------------------------------------------------------------------------
//Чтение из файла
void __fastcall TForm1::Button6Click(TObject *Sender)
{
FILE *matr;
FILE *pch;
String s=ComboBox1->Text,p=s+"p";
Button1->Enabled=true;Button2->Enabled=true;Button3->Enabled=true;
Button4->Enabled=true;CheckBox2->Enabled=true;
epsilon=StrToFloat(Edit2->Text);
matr=fopen(s.c_str(),"rt");
fscanf(matr,"%d\n",&n);
pch=fopen(p.c_str(),"rt");
int tn=StrToInt(Edit1->Text);
if (tn>n) MessageBox(0,"Размерность матрицы в файле меньше заданной","Ошибка",MB_OK);
else {
n=tn;
f=new double [n];
a=new double* [n];
StringGrid1->ColCount=n;
StringGrid1->RowCount=n;
for (int i=0;i<6;i++)
{
sg[i]->RowCount=n;
sg[1]->Cells[0][i]="";
}
for (int i=0;i<n;i++)
a[i]=new double [n];
for (int i=0;i<n;i++)
{
float r;
fscanf(pch,"%f",&r);
f[i]=r;
sg[0]->Cells[0][i]=FloatToStr(f[i]);
for (int j=0;j<n;j++)
{
fscanf(matr,"%f",&r);
a[i][j]=r;
StringGrid1->Cells[j][i]=FloatToStr(a[i][j]);
}
}}
fclose(matr);fclose(pch);
}
//---------------------------------------------------------------------------
//Запись в файл
void __fastcall TForm1::Button7Click(TObject *Sender)
{
FILE *matr;
FILE *pch;
String s=ComboBox2->Text,p=s+"p";
matr=fopen(s.c_str(),"w");
fprintf(matr,"%d\n",n);
pch=fopen(p.c_str(),"w");
for (int i=0;i<n;i++)
{
fprintf(pch,"%f\n",f[i]);
for (int j=0;j<n;j++)
fprintf(matr,"%f ",a[i][j]);
fprintf(matr,"\n");
}
fclose(matr);fclose(pch);
}