|
Хочу получить удостоверение. Сколько стоит оплата? |
Конструкторы и деструкторы
Конструктор (constructor) — это функция-член (метод) класса. Конструкторы используются для инициализации переменных класса или для выделения памяти. Они всегда имеют такое же имя, как и класс, в котором они определены. Конструкторы располагают дополнительными возможностями: они могут иметь аргументы и их можно перегружать.
Деструктор (destructor) — это метод класса, использующийся обычно для освобождения памяти, выделенной из свободной памяти. Деструктор, так же как и конструктор, имеет такое же имя, как и класс, в котором он описан, перед которым находится символ "тильда" (~). Деструкторы являются дополнениями конструкторов. Деструктор вызывается автоматически при использовании операции delete по отношению к указателю класса или в случае, когда программа выходит из области действия объекта класса. Деструкторы, в отличие от конструкторов, не могут иметь параметров, и их нельзя перегружать.
В приводимой ниже программе конструктор nonlinear_regression() используется для инициализации локальных переменных класса nonlinear_regression. Программа рассчитывает нелинейную регрессию. Алгоритм расчета нелинейной регрессии хорошо описан в книге К. Эберт, Х. Эдерер /Компьютеры. Применение в химии. М.: Мир., 1988. С.284.
//==========================================================
// Name : constructor.cpp
// Author : Marat
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//==========================================================
#include <iostream>
using namespace std;
#include<stdlib.h>
#include<math.h>
#define ARRAY_SIZE 100 //Размер матрицы
#define np 64 //Число пар данных
//Экспериментальные значения X(i)
double xx[np+1]={0.000, 0.000, 0.005, 0.010, 0.015, 0.020, 0.025, 0.030, 0.035, 0.040, 0.045,
0.050, 0.055, 0.060, 0.065, 0.070, 0.075, 0.080, 0.085, 0.090, 0.095, 0.100,
0.105, 0.110, 0.115, 0.120, 0.125, 0.130, 0.135, 0.140, 0.145, 0.150, 0.155,
0.160, 0.165, 0.170, 0.175, 0.180, 0.185, 0.190, 0.195, 0.200, 0.205, 0.210,
0.215, 0.220, 0.225, 0.230, 0.235, 0.240, 0.245, 0.250, 0.255, 0.260, 0.265,
0.270, 0.275, 0.600, 0.605, 0.610, 0.615, 0.620, 0.625, 0.630, 0.635 };
//Экспериментальные значения Y(i)
double yy[np+1]={0.000000, 1.000000, 0.854415, 0.734266, 0.627988, 0.535742, 0.459174, 0.395416,
0.337545, 0.288678, 0.249475, 0.213886, 0.185657, 0.157447, 0.135157, 0.118451,
0.099275, 0.085432, 0.074251, 0.063035, 0.054768, 0.047787, 0.039426, 0.034518,
0.030223, 0.026509, 0.023732, 0.019806, 0.014693, 0.011894, 0.009542, 0.006593,
0.005535, 0.005540, 0.007713, 0.003393, 0.004965, 0.001981, 0.003614, 0.000934,
0.0000215, 0.0002637, 0.0013670, 0.0011571, -.0006458, 0.00199994, -.0035763,
-.0026426, -.0023520, -.0026480, -.0054493, -.0026830, -.0028068, -.0018326,
-.0008719, -.0006889, -.0008531, -.0052879, -.0058611, -.0047900, -.0052341,
-.0022847, -.0024500, -.0030974, -.0};
class nonlinear_regression {
long double a[ARRAY_SIZE][ARRAY_SIZE], b[ARRAY_SIZE][ARRAY_SIZE], u[ARRAY_SIZE][ARRAY_SIZE];
long double v[ARRAY_SIZE][ARRAY_SIZE], w[ARRAY_SIZE][ARRAY_SIZE], f2[ARRAY_SIZE][ARRAY_SIZE];
long double x[ARRAY_SIZE], x9[ARRAY_SIZE], f[ARRAY_SIZE], f9[ARRAY_SIZE];
long double f0[ARRAY_SIZE], f1[ARRAY_SIZE], h[ARRAY_SIZE], k[ARRAY_SIZE];
int i,j;
int n;
long double ss; //Сумма квадратов отклонений
long double X,Y;
long double ff; //Коэффициент оптимизации
long double sm;
public:
//Конструктор
nonlinear_regression() {n=3; ff=1; sm=1E100;}
//Деструктор
~nonlinear_regression() {cout<<"\nThats all right!"<<endl;}
void compute();
void input();
void inversion_matrix();
void partial_derivative();
void print();
void optimization_factor();
void sum_of_square_deviations();
void calculation();
void regression();
void function();
};
void nonlinear_regression::compute()
{
input();
for(int l=0;l<1000;l++)
{
l++;
//Вычисление частных производных
partial_derivative();
//Обращение матрицы
inversion_matrix();
for(i=1;i<=n;i++)
{
h[i]=0;
for(j=1;j<=n;j++)
{
h[i]+=w[i][j]*f9[j];
}
}
//Вывод данных
if(l>998) print();
//Вычисление коэффициента оптимизации
optimization_factor();
for(i=1;i<=n;i++)
{
x9[i]-=ff*h[i];
}
}
}
void nonlinear_regression::input()
{
cout<<"\nInitial approximation input ";
for(i=1;i<=n;i++)
{
cout<<"\nk["<<i<<"] = ";
cin>>x[i];
x9[i]=x[i];
}
}
//Обращение матрицы.
//Исходная матрица A,
//Обращенная матрица W
void nonlinear_regression::inversion_matrix()
{
int z,t,k;
double s;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
b[i][j]=0;
v[i][j]=0;
if(i!=j) goto alpha;
b[i][j]=1;
v[i][j]=1;
alpha: ;
}
}
for(z=1;z<n;z++)
{
s=0;
//Поиск ведущего элемента
for(i=z;i<=n;i++)
{
if(s>fabs(a[i][z])) goto beta;
s=fabs(a[i][z]);
t=i;
beta: ;
}
//Обмен z-й строки с t-й
for(i=1;i<=n;i++)
{
s=a[z][i];
a[z][i]=a[t][i];
a[t][i]=s;
}
if(fabs(a[z][z])>1E-30) goto gamma;
cout<<"\nThe matrix cannot be inversed!"; exit(1);
gamma: v[z][z]=0;
v[t][t]=0;
v[z][t]=1;
v[t][z]=1;
//Исключение недиагональных элементов методом Жордана-Гаусса
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(i==z) goto teta;
if(j==z) goto epsilon;
u[i][j]=a[i][j]-a[z][j]*a[i][z]/a[z][z];
goto psi;
teta: if(i==j) goto omega;
u[i][j]=-a[i][j]/a[z][z];
goto psi;
omega: u[z][z]=1/a[z][z];
goto psi;
epsilon: u[i][z]=a[i][z]/a[z][z];
psi: ;
}
}
//Умножение матриц
//B = V * B
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
w[i][j]=0;
for(k=1;k<=n;k++)
{
w[i][j]+=v[i][k]*b[k][j];
}
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
b[i][j]=w[i][j];
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
a[i][j]=u[i][j];
v[i][j]=0;
if(i==j) v[i][j]=1;
}
}
}
//Результат умножения матрицы A на матрицу B
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
w[i][j]=0;
for(k=1;k<=n;k++)
{
w[i][j]+=a[i][k]*b[k][j];
}
}
}
}
//Вычисление частных производных
//(элементы массива a[]) в точках x9
void nonlinear_regression::partial_derivative()
{
int i3,j3;
double di;
int ip;
ss=0;
for(int i=1;i<=n;i++)
{
f9[i]=0;
k[i]=x9[i];
for(j=1;j<=n;j++)
{
a[i][j]=0;
}
}
for(int ip=1;ip<=np;ip++)
{
X=xx[ip];
function();
di=yy[ip]-Y;
ss+=pow(di,2);
for(int i3=1;i3<=n;i3++)
{
f9[i3]-=di*f1[i3];
for(j3=i3;j3<n;j3++)
{
a[i3][j3]-=di*f2[i3][j3]+f1[i3]*f1[j3];
}
}
}
for(int i3=1;i3<=n;i3++)
{
for(j3=i3;j3<=n;j3++)
{
a[j3][i3]=a[i3][j3];
}
}
}
//Y - функция, входящая в уравнение регрессии,
//F1() и F2() - ее первые и вторые производные
//по параметрам k
// Y=k(1) + k(2)*exp(-k(3)*X)
void nonlinear_regression::function()
{
f1[1]=1;
f2[1][1]=0;
f2[1][2]=0;
f2[1][3]=0;
f1[2]=exp(-k[3]*X);
f2[2][2]=0;
f2[2][3]=-X*f1[2];
f1[3]=k[2]*f2[2][3];
f2[3][3]=-X*f1[3];
Y=k[1]+k[2]*f1[2];
}
//Вычисление суммы квадратов отклонений
void nonlinear_regression::sum_of_square_deviations()
{
ss=0;
for(int i=1;i<=np;i++)
{
X=xx[i];
regression();
Y-=yy[i];
ss+=pow(Y,2);
}
}
//Уравнение регрессии
void nonlinear_regression::regression()
{
Y=k[1]+k[2]*exp(-k[3]*X);
}
//Вычисление коэффициента оптимизации ff
void nonlinear_regression::optimization_factor()
{
double fm,df;
ff=0.6;
fm=0;
df=0.5;
dzeta: calculation();
if(ss<sm) {sm=ss; fm=ff; ff+=df; goto dzeta;}
else {ff=fm-df;}
omega: calculation();
if(ss<sm) {sm=ss; fm=ff; ff-=df; goto omega;}
for(j=0;j<=7;j++)
{
df/=2;
ff=fm+df;
calculation();
if(ss<sm) {sm=ss;fm=ff; goto csi;}
else {ff=fm-df; calculation();}
if(ss<sm) {sm=ss; fm=ff;}
csi:;
}
ff=fm;
}
//Вспомогательная функция
void nonlinear_regression::calculation()
{
for(int i=1;i<=n;i++)
{
k[i]=x9[i]-ff*h[i];
}
sum_of_square_deviations();
}
//Вывод данных на экран
void nonlinear_regression::print()
{
for(int i=1;i<=n;i++)
{
cout<<"\nk["<<i<<"] = "<<x9[i]<<"+/-"<<pow(fabs(w[i][i]*ss/(np-n)),2);
}
cout<<"\nThe sum of square deviations is "<<ss<<endl;
}
int main() {
nonlinear_regression data;
data.compute();
return 0;
}
Результат:
Initional approximation input k[1]=1 k[2]=1 k[3]=10 k[1]=-0.106121+/-1.37518e-007 k[2]=0.711263 +/-5.13888e-006 k[3]=10+/-0 The sum of square deviations is 0.645081