Границы применимости алгоритма



Несмотря на то, что алгоритм почти во всех случаях дал хорошие резуль, в некоторых измерениях (6 из 144) выполнение алгоритма заканчивалось неудачей. Пример такого измерения приведён на рисунке 10.

Рисунок 10. Пример измерения, на котором алгоритм оказался неэффективным

 

Отказ алгоритма объясняется выбросом на графиках P(t) и h(t). Объяснить нелинейность можно посторонними вибрациями во время измерения (например, кто-то схватился за прибор). В таких случаях для обработки приходится указывать точку контакта вручную.
Заключение

 

Созданный алгоритм показал свою эффективность и точность в большом числе случаев. Однако, в некоторых случаях (см. рис. 10) он может оказаться неэффективным. С учётом небольшого количества подобных случаев (около 5%) время обработки данных сокращается более чем в 20 раз. Наблюдается уменьшение случайной погрешности в случае использования алгоритма. На текущий момент оптимальным решением является совмещение автоматического и ручного режимов.


Приложение 1. Алгоритм метода наименьших квадратов

 

Пусть есть некоторый набор экспериментальных точек, имеющих две координаты — (xi,yi) и число таких точек равно n. Задача метода наименьших квадратов заключается в нахождении коэффициентов линейной зависимости, при которых функция двух переменных а и b

 

 

принимает наименьшее значение. То есть, при данных а и b сумма квадратов отклонений экспериментальных данных от найденной прямой будет наименьшей. В этом вся суть метода наименьших квадратов.
Таким образом, решение примера сводится к нахождению экстремума функции двух переменных.
Составляется и решается система из двух уравнений с двумя неизвестными. Находим частные производные функции

 

по переменным а и b, приравниваем эти производные к нулю.


 

Решаем полученную систему уравнений любым методом (например, методом подстановки или методом Крамера) и получаем формулы для нахождения коэффициентов по методу наименьших квадратов.



При данных а и b функция

 

 

принимает наименьшее значение.

 

 


Приложение 2. Листинг программы на С++ автоматического определения точки касания.

 

BOOL CNSCtrlMath::FindZeroLoadingPointA(double* pX, double* pY, int i0, int i1, int nCourse, int nTurn, double &fAngle, double &fZero, int &k0,/*rusakov*/double fLevel)

// nCourse - "1" - вперёд, "-1" - назад (работает только 1)

// nTurn - "1" - направо, "-1" - налево (работает только -1)

// i0 - first point

// i1 - last point

// k0 - beginning of search and result

// fLevel - кол-во среднеквадратичных отклонений, определяющее окрестность аппроксимирующей прямой

// GoBack - "1" - идти назад после нахождения поворота, пока возможно; "0" - никуда не идти

// fLevelBack - кол-во среднеквадратичных отклонений, определяющее окрестность аппроксимирующей прямой при движении назад

 

{

if(i1 <= i0 + 2) return FALSE;

 

int i=0, j=0, knew=0;

 

double fSxL=0.0;   // сумма значений xi

double fSyL=0.0;   // сумма значений yi

double fSxxL=0.0; // сумма квадратов xi*xi

double fSyyL=0.0; // сумма квадратов yi*yi

double fSxyL=0.0; // сумма произведений xi*yi

double aL=0.0, bL=0.0, cL=0.0;

double fAngleL=0.0, fZeroL=0.0, fSd2L=0.0;

 

double fSxR=0.0;   // сумма значений xi

double fSyR=0.0;   // сумма значений yi

double fSxxR=0.0; // сумма квадратов xi*xi

double fSyyR=0.0; // сумма квадратов yi*yi

double fSxyR=0.0; // сумма произведений xi*yi

double aR=0.0, bR=0.0, cR=0.0;

double fAngleR=0.0, fZeroR=0.0, fSd2R=0.0;

 

double fSd2=0.0, fSigma=0.0; /*, rusakov fLevel=3.0;*/

 

for(i=i0; i<=i0+1; i++) {

       fSxL += pX[i];

       fSyL += pY[i];

       fSxxL += pX[i] * pX[i];

       fSyyL += pY[i] * pY[i];

       fSxyL += pX[i] * pY[i];

}

aL = 2.0*fSxyL - fSxL*fSyL;

bL = fSxxL*fSyL - fSxL*fSxyL;

cL = 2.0*fSxxL - fSxL*fSxL;

fAngleL = aL/cL;

fZeroL = bL/cL;

fSd2L = fSyyL + fAngleL*fAngleL*fSxxL + 2.0*fZeroL*fZeroL - 2.0*fAngleL*fSxyL - 2.0*fZeroL*fSyL + 2.0*fAngleL*fZeroL*fSxL;

 

for(i=i0+2; i<=i1; i++) {

       fSxR += pX[i];

       fSyR += pY[i];

       fSxxR += pX[i] * pX[i];

       fSyyR += pY[i] * pY[i];

       fSxyR += pX[i] * pY[i];

}

aR = double(i1-i0-1)*fSxyR - fSxR*fSyR;

bR = fSxxR*fSyR - fSxR*fSxyR;

cR = double(i1-i0-1)*fSxxR - fSxR*fSxR;

fAngleR = aR/cR;

fZeroR = bR/cR;

fSd2R = fSyyR + fAngleR*fAngleR*fSxxR + double(i1-i0-1)*fZeroR*fZeroR - 2.0*fAngleR*fSxyR - 2.0*fZeroR*fSyR + 2.0*fAngleR*fZeroR*fSxR;

 

fSigma = sqrt((fSd2L + fSd2R)/double(i1-i0));

fSd2 = fSd2L + fSd2R;

knew = i0 + 1;

 

for(i=i0+2; i<=i1-1; i++) {

       fSxL += pX[i];

       fSyL += pY[i];

       fSxxL += pX[i] * pX[i];

       fSyyL += pY[i] * pY[i];

       fSxyL += pX[i] * pY[i];

       aL = double(i-i0+1)*fSxyL - fSxL*fSyL;

       bL = fSxxL*fSyL - fSxL*fSxyL;

       cL = double(i-i0+1)*fSxxL - fSxL*fSxL;

       fAngleL = aL/cL;

       fZeroL = bL/cL;

       fSd2L = fSyyL + fAngleL*fAngleL*fSxxL + double(i-i0+1)*fZeroL*fZeroL - 2.0*fAngleL*fSxyL - 2.0*fZeroL*fSyL + 2.0*fAngleL*fZeroL*fSxL;

 

       fSxR -= pX[i];

       fSyR -= pY[i];

       fSxxR -= pX[i] * pX[i];

       fSyyR -= pY[i] * pY[i];

       fSxyR -= pX[i] * pY[i];

       aR = double(i1-i)*fSxyR - fSxR*fSyR;

       bR = fSxxR*fSyR - fSxR*fSxyR;

       cR = double(i1-i)*fSxxR - fSxR*fSxR;

       fAngleR = aR/cR;

       fZeroR = bR/cR;

       fSd2R = fSyyR + fAngleR*fAngleR*fSxxR + double(i1-i)*fZeroR*fZeroR - 2.0*fAngleR*fSxyR - 2.0*fZeroR*fSyR + 2.0*fAngleR*fZeroR*fSxR;

 

       if(fSd2 > fSd2L + fSd2R) {

             fSd2 = fSd2L + fSd2R;

             knew = i;

       }

}

 

// go back while possible

fSxL=0.0, fSyL=0.0, fSxxL=0.0, fSyyL=0.0, fSxyL=0.0;

for(i=i0; i<=knew; i++) {

       fSxL += pX[i];

       fSyL += pY[i];

       fSxxL += pX[i] * pX[i];

       fSyyL += pY[i] * pY[i];

       fSxyL += pX[i] * pY[i];

}

aL = double(knew-i0+1)*fSxyL - fSxL*fSyL;

bL = fSxxL*fSyL - fSxL*fSxyL;

cL = double(knew-i0+1)*fSxxL - fSxL*fSxL;

fAngleL = aL/cL;

fZeroL = bL/cL;

     

fSd2L = fSyyL + fAngleL*fAngleL*fSxxL + double(knew-i0+1)*fZeroL*fZeroL - 2.0*fAngleL*fSxyL - 2.0*fZeroL*fSyL + 2.0*fAngleL*fZeroL*fSxL;

fSigma = sqrt(fSd2L/double(knew-i0));

 

while(knew > i0 + 2 && pY[knew+1] > fAngleL*pX[knew+1] + fZeroL + fLevel*fSigma) {

// while(knew > i0 + 2 && pY[knew] > fAngleL*pX[knew] + fZeroL) {

       fSxL -= pX[knew];

       fSyL -= pY[knew];

       fSxxL -= pX[knew] * pX[knew];

       fSyyL -= pY[knew] * pY[knew];

       fSxyL -= pX[knew] * pY[knew];

       knew--;

       aL = double(knew-i0+1)*fSxyL - fSxL*fSyL;

       bL = fSxxL*fSyL - fSxL*fSxyL;

       cL = double(knew-i0+1)*fSxxL - fSxL*fSxL;

       fAngleL = aL/cL;

       fZeroL = bL/cL;

       //fSd2L = fSyyL + fAngleL*fAngleL*fSxxL + double(knew-i0+1)*fZeroL*fZeroL - 2.0*fAngleL*fSxyL - 2.0*fZeroL*fSyL + 2.0*fAngleL*fZeroL*fSxL;

       //fSigma = sqrt(fSd2L/double(knew-i0));

}

 

k0 = knew;

fAngle = fAngleL;

fZero = fZeroL;

return TRUE;

}


Библиография

1. А. Мешков, Ю. Тихомиров / Visual C++ и MFC. Программирование для Windows NT и Windows 95: в трёх томах — СПб: BHV — Санкт-Петербург, 1997

2. Фрэнк Крокет / MFC. Мастерская разработчика. Пер. с англ. — М.: Издательский отдел «Русская Редакция» ТОО «Channel Trading Ltd.», 1998.

3. В.Н. Решетов, Е.О. Баранова / Сканирующая зондовая микроскопия: учебно-методическое пособие — Троицк: ФГУ ТИСНУМ, 2011

4. В.Л. Миронов / Основы сканирующей зондовой микроскопии: учебное пособие для студентов старших курсов высших учебных заведений — Нижний Новгород: Российская Академия Наук, Институт физики микроструктур, 2004

5. W.C. Oliver, G.M. Pharra / Measurement of hardness and elastic modulus by instrumented indentation: Advances in understanding and refinements to methodology — Journal of Materials Research, 2004, vol. 19 (1), p.3-20


Дата добавления: 2018-02-18; просмотров: 364; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!