- •Нахождение экстремумов
- •Построение графика
- •Численный метод нахождения экстремума
- •Теоретические вопросы
- •Метод деформируемого многогранника (Нелдера Мида)
- •Метод наискорейшего спуска
- •Метод сопряженных направлений и его модификации
- •Метод Ньютона и его модификации
- •Метод дробления шага
- •Скрипт MATLAB для построения графика
- •Описание функции
- •Текст скрипта
- •Реализация алгоритма Ньютона
- •Тест реализации алгоритма Ньютона
CТест реализации алгоритма Ньютона
1using System;
2using NUnit.Framework;
3
4namespace MathUtilities.Tests
5{
6
7
8
9
[TestFixture]
public class NewtonOptimizerTest
{
[Test]
10[TestCase(new double[]{0, 0}, new double[]{1, 1})]
11public void TestOptimal(double[] start, double[] expected)
12{
13
14
15
var op = new NewtonOptimizer(Function, start); var got = op.GetOptimal();
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Assert.IsTrue(equals(got.items, expected));
}
[Test]
public void TestMatrixReverse()
{
var matrixAsArray = new double[2][]; matrixAsArray[0] = new double[]{0.5, 1}; matrixAsArray[1] = new double[]{2, 2};
var expectedMatrixAsArray = new double[2][]; expectedMatrixAsArray[0] = new double[]{-2, 1}; expectedMatrixAsArray[1] = new double[]{2, -0.5}; var matrix = new Matrix(matrixAsArray);
var got = matrix.GetReversed();
var expected = new Matrix(expectedMatrixAsArray);
32
33
34
35
36
37
38
39
40
41
42
43
44
45
var gotArray = TwoDimensionalIntoOneDimensional(got.items);
var expectedArray = TwoDimensionalIntoOneDimensional(expected.items);
Assert.IsTrue(equals(gotArray, expectedArray));
}
[Test]
public void TestMatrixAction()
{
var matrixAsArray = new double[3][]; matrixAsArray[0] = new double[]{2, 4, 0}; matrixAsArray[1] = new double[]{-2, 1, 3}; matrixAsArray[2] = new double[]{-1, 0, 1};
21
46
47
48
var matrix = new Matrix(matrixAsArray); var vector = new Vector(1, 2, -1);
49 |
var got = matrix * vector; |
50 |
var expected = new Vector(10, -3, -2); |
51 |
Assert.IsTrue(equals(got.items, expected.items)); |
52 |
} |
53
54[Test]
55[TestCase(new double[]{1, 1}, 0, 0)]
56[TestCase(new double[]{0, 0}, -200, 0)]
57public void TestAnotherFunctionPartial(double[] arr, double expected1, ,! double expected2)
58{
59 |
var a = new Derivative(Function); |
60 |
var partial1 = a.GetPartialDerivative(new Vector(arr), 0); |
61 |
var partial2 = a.GetPartialDerivative(new Vector(arr), 1); |
62 |
Assert.IsTrue(equals(partial1, expected1)); |
63 |
Assert.IsTrue(equals(partial2, expected2)); |
64 |
} |
65
66[Test]
67[TestCase(new double[]{0, 0}, 0)]
68[TestCase(new double[]{1, 1}, 2)]
69public void TestPartial1(double[] arr, double expected)
70{
71
72
73
var a = new Derivative(TypicalFunction);
var partial1 = a.GetPartialDerivative(new Vector(arr), 0);
74 |
Assert.IsTrue(equals(expected, partial1)); |
75 |
} |
76
77[Test]
78[TestCase(new double[]{0, 0}, 0)]
79[TestCase(new double[]{1, 1}, 2)]
80public void TestPartial2(double[] arr, double expected)
81{
82
83
var a = new Derivative(TypicalFunction);
var partial2 = a.GetPartialDerivative(new Vector(arr), 1);
84 |
|
85 |
Assert.IsTrue(equals(expected, partial2)); |
86 |
} |
87
88[Test]
89[TestCase(new double[]{0, 0}, new double[]{0, 0})]
90[TestCase(new double[]{1, 1}, new double[]{2, 2})]
91public void TestGradient(double[] arr, double[] expected)
22
92
93
94
95
96
97
98
{
var a = new Derivative(TypicalFunction);
var gradient = a.GetGradient(new Vector(arr));
Assert.IsTrue(equals(gradient, new Vector(expected)));
}
99[Test]
100[TestCase(new double[]{0, 0}, new double[]{2, 0, 0, 2})]
101[TestCase(new double[]{1, 1}, new double[]{2, 0, 0, 2})]
102public void TestSecondPartial(double[] arr, double[] expected)
103{
104
105
var array = new double[4];
106 |
var a = new Derivative(TypicalFunction); |
107 |
for (int i = 0; i < 2; i++) |
108 |
for (int j = 0; j < 2; j++) |
109 |
array[2 * i + j] = a.GetSecondPartialDerivative(new |
|
,! Vector(arr), i, j); |
110 |
|
111 |
Assert.IsTrue(equals(array, expected)); |
112 |
} |
113 |
|
114[Test]
115[TestCase(new double[]{0, 0}, new double[] {2, 0, 0, 2})]
116[TestCase(new double[]{1, 1}, new double[] {2, 0, 0, 2})]
117public void TestHessian(double[] arr, double[] expected)
118{
119 |
var |
a = new Derivative(TypicalFunction); |
120 |
var |
hessian = a.GetHessian(new Vector(arr)); |
121 |
var |
oneDimensionalHessian = |
|
,! |
TwoDimensionalIntoOneDimensional(hessian.items); |
122 |
|
|
123 |
Assert.IsTrue(equals(oneDimensionalHessian, expected)); |
|
124 |
} |
|
125 |
|
|
126/// <summary>
127/// x^2 + y^2
128/// </summary>
129/// <remark>
130/// F'(0, 0) = 0;
131/// F'(1, 1) = 2;
132/// </remark>
133private double TypicalFunction(Vector vector) =>
134 Math.Pow(vector.Get(0), 2) + Math.Pow(vector.Get(1), 2);
135
136
23
137/// <summary>
138/// (x_2 - x_1^2)^2 + 100 * (1 - x_1)^2
139/// </summary>
140private static double Function(Vector vector) =>
141 |
Math.Pow(vector.Get(1) - Math.Pow(vector.Get(0), 2), 2) + 100 * |
|
,! Math.Pow(1 - vector.Get(0), 2); |
142
143/// <summary>
144/// Переводит двумерный массив в длинный одномерный.
145/// </summary>
146/// <param name="arr">двумерный массив</param>
147/// <returns>одномерный массив, ячейки строк идут друг за ,! другом</returns>
148private double[] TwoDimensionalIntoOneDimensional(double[][] arr)
149{
150
151
152
153
154
155
156
157
158
159
160
161
162
var length = (int) arr.Length;
var answerLength = (int) Math.Pow(length, 2); var answer = new double[answerLength];
for (var i = 0; i < length; i++) for (var j = 0; j < length; j++)
answer[2 * i + j] = arr[i][j];
return answer;
}
private bool equals(Vector vec1, Vector vec2) => equals(vec1.items, vec2.items);
163/// <summary>
164/// Примерно сравнивает массивы.
165/// Последовательно использует функцию примерного сравнивания чисел.
166/// </summary>
167/// <param name="arr1">первый массив</param>
168/// <param name="arr2">второй массив</param>
169/// <returns>истина, если массивы примерно равны</returns>
170private bool equals(double[] arr1, double[] arr2)
171{
172
173
174
175
for (var i = 0; i < arr1.Length; i++) if (!equals(arr1[i], arr2[i]))
return false;
176 |
return true; |
177 |
} |
178 |
|
179
180
181
///<summary>
///Примерно сравнивает числа.
///</summary>
24
182/// <param name="a">первое число</param>
183/// <param name="b">второе число</param>
184/// <returns>истина, если числа равны хотя бы на [TYPICAL_PRECISION] ,! порядков</returns>
185private bool equals(double a, double b)
186{
187 |
var |
eq = Math.Max(Infinitesimal.GetPrecision(a), |
|
,! |
Infinitesimal.GetPrecision(b)); |
188 |
if (Math.Abs(a - b) < eq) |
|
189 |
|
return true; |
190 |
|
|
191 |
return false; |
192}
193}
194}
25