Опубликован: 10.12.2015 | Уровень: для всех | Доступ: платный
Лекция 20:

Конструкторы и деструкторы

< Лекция 19 || Лекция 20 || Лекция 21 >

Конструктор (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
< Лекция 19 || Лекция 20 || Лекция 21 >
Зося Ковалева
Зося Ковалева

Хочу получить удостоверение. Сколько стоит оплата?

Aleksey Aplaev
Aleksey Aplaev
Россия, Chelybinsk
Александр Сидоров
Александр Сидоров
Россия, Самара