Рядовая университется задачка, но появились трудности, с которыми долгое время не могу справиться.
Дана исходная функция (описана в коде JS)
Дана точность.
Необходимо найти точку минимума, используя метод наискорейшего градиентного спуска.
Проблема: Метод должен сходиться к единственной точке для любого начального вектора. Мое решение существенно зависит от исходных, вводимых данных.
Предположение, где может быть ошибка: Мне кажется, что-то с условием остановки, в самом условии while.
HTML-код.
Здесь вводим точность и координаты трехмерного начального вектора.
<html>
<head>
<title>МНГС</title>
<script src="6.js"></script>
</head>
<body>
<h1><div id="one">Вычисление точки минимума для заданной функции (МНГС)</div></h1>
<h2><div id="third"><form name="forma11">
Введите точность:<input type="text""size="20" name="e" value="0.000001" onFocus="this.value=''" onBlur="if (this.value==''){this.value='0'}"> <br>
Введите начальный вектор:<br>
Первая координата:<input type="text""size="10" name="x00" value="1" onFocus="this.value=''" onBlur="if (this.value==''){this.value='0'}"> <br>
Вторая координата:<input type="text""size="10" name="x01" value="0" onFocus="this.value=''" onBlur="if (this.value==''){this.value='0'}"> <br>
Третья координата:<input type="text""size="10" name="x02" value="0" onFocus="this.value=''" onBlur="if (this.value==''){this.value='0'}"> <br>
<input type="button" value="Определить" onClick="numword(forma11);">
<input type="reset" value="Отменить"><hr>
</div>
</div></h2>
</body>
</html>
Javascript - код
//МНГС
function f(x, y, z)
{
var f=2*x*x+ 3.2*y*y+4.2*z*z+x*y-y*z+x*z+x-2*y+3*z+2; // заданная квадратичная форма
return f
}
function gradX(x, y, z)
{
var gradX=4*x+y+z+1;
return gradX
}
function gradY(x, y, z)
{
var gradY=6.4*y+x-z-2;
return gradY
}
function gradZ(x, y, z)
{
var gradZ=8.4*z+x-y+3;
return gradZ
}
function numword(obj)
{
var e =1*obj.e.value; //точность из html-формы
var x0 = new Array(3); //вектор из html-формы
x0[0]=1*obj.x00.value;
x0[1]=1*obj.x01.value;
x0[2]=1*obj.x02.value;
var x1 = new Array(3);
var A = new Array (3); //матрица коэффициентов квадратичной формы
for (var i=0; i<3; i++)
{
A[i]=new Array(3);
}
var m=0; // коэффициент "мю" из МНГС
A[0][0]=2; //задание коэффициентов
A[1][1]=3.2;
A[2][2]=4.2;
A[0][1]=A[1][0]=A[2][0]=A[0][2]=1;
A[2][1]=A[1][2]=-1;
var Q= new Array(3); //вектор-градиент (Ax+b)
for (var j=0; j<3; j++)
{
Q[j]=0;
}
var count=0; //счетчиков шагов
var grad= new Array(3); //градиент
var Agrad= new Array(3); // матрица*градиент
for (var j=0; j<3; j++)
{
Agrad[j]=0;
}
var fi = new Array(100000); //массив для значений функций
var keyQ=0; произведение Градиент*матрица*градиент
var fx1=1; //два соседних значения функции
var fx0=0;
while (Math.abs(fx1-fx0)>e)
{
for (var j=0; j<3; j++)
{
x1[j]=x0[j]; //присвоили новое значение
}
fx1 = f(x1[0],x1[1],x1[2]);
grad[0]=gradX(x1[0], x1[1], x1[2]); //градиенты в новой точке
grad[1]=gradY(x1[0], x1[1], x1[2]);
grad[2]=gradZ(x1[0], x1[1], x1[2]);
for (var i=0; i<3; i++)
{
for (var j=0; j<3; j++)
{
Agrad[i]+=A[i][j]*grad[j]; //A*градиент
}
}
for (var j=0; j<3; j++)
{
keyQ+=grad[j]*Agrad[j]; градиент*А*градиент
}
var quatGrad=0;
for (var j=0; j<3; j++)
{
quatGrad+=grad[j]*grad[j]; //градиент в квадрате
}
m=-(quatGrad)/keyQ; //коэффициент спуска
for (var j=0; j<3; j++)
{
x0[j]=x1[j]+m*grad[j]; // новая точка
}
fx0 = f(x0[0],x0[1],x0[2]); //новое значение
fi[count]=fx0; //записали в массив
count++;
}
alert ("Шагов сделано: " + count);
var keyF = 0;
keyF = fi[count-1]; //-1 т.к. цикл делает на 1 шаг больше, и последнее значение fx1>fx0
x0[0] = x0[0].toFixed(3);
x0[1] = x0[1].toFixed(3);
x0[2] = x0[2].toFixed(3);
keyF = keyF.toFixed(3);
alert("точка минимума = [" + x0[1]+", " + x0[1] + ", " +x0[2]+"], значение функции в этой точке " + keyF);
}