Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторная работа 1. 6 вар. Трофимов-2019.pdf
Скачиваний:
285
Добавлен:
19.02.2020
Размер:
175.99 Кб
Скачать

DТест анализатора пузырьковой сортировки

1using static System.Math;

2using NUnit.Framework;

3

4namespace MathUtilities.Tests

5{

6[TestFixture]

7 [TestOf(typeof(InfiniteAnalyzer))]

8public class InfiniteAnalyzerTest

9{

10[Test]

11public void TestAsymptote()

12{

13

var ia = new InfiniteAnalyzer();

14

var a = ia.GetAsymptote();

15

Assert.AreEqual(2, Round(a.Alpha));

16}

17}

18}

25

EПрограммный анализ БМФ многих переменных

1using static System.Math;

2using System;

3

4namespace MathUtilities

5{

6

7

8

9

///<summary>

///Работа с функцией многих переменных.

///</summary>

public class MultivariateAnalyzer

10{

11/// <summary>

12/// Функция многих переменных для рассмотрения.

13/// </summary>

14private readonly Func<Vector, double> _multivariateFunction;

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

///<summary>

///Точка рассмотрения. В задаче - просто X_0.

///</summary>

private readonly Vector _pointOfView;

///<summary>

///Направление движения. В задаче - просто R.

///</summary>

private readonly Vector _vector;

///<summary>

///Анализатор функции одной переменной.

///</summary>

private readonly InfinitesimalAnalyzer _analyzer;

31

32

33

34

35

36

37

38

39

40

41

public MultivariateAnalyzer(

Func<Vector, double> multivariateFunction, Vector pointOfView,

Vector vector

) {

_multivariateFunction = multivariateFunction; _pointOfView = pointOfView;

_vector = vector;

_analyzer = new InfinitesimalAnalyzer(Function);

}

42/// <summary>

43/// Рассчитывает табличный вид бесконечно малой дополнительной функции.

44/// </summary>

45/// <returns></returns>

26

46

47

48

public TableItem[] GetTableRepresentation() => _analyzer.GetTableRepresentation();

49/// <summary>

50/// Рассчитывает асимптоту бесконечно малой дополнительной функции.

51/// </summary>

52/// <returns></returns>

53public Asymptote GetAsymptote() =>

54

_analyzer.GetAsymptote();

55

56/// <summary>

57/// Рассчитывает коэффициент бесконечно малой дополнительной функции.

58/// </summary>

59/// <returns></returns>

60public double GetCoefficient() =>

61

_analyzer.GetCoefficient();

62

63/// <summary>

64/// Передаёт точки кругов коэфициента `C`.

65/// </summary>

66/// <param name="iterationsAmount">количество точек для ,! построения</param>

67/// <returns>точки кругов</returns>

68public Vector[] GetCircle(int iterationsAmount = 180)

69{

70

71

72

73

74

75

76

77

// матрица поворота на 360 / iterations градусов в радианах

var rotationMatrix = Math.GetRotationMatrix(PI / 90);

// создаём пустой массив

var answer = new Vector[iterationsAmount];

// копируем вектор сюда

var vector = _vector;

// такая же функция, что и Function

Func<double, double> f;

78

 

79

// повторяем много раз

80

for (int i = 0; i < iterationsAmount; i++)

81

{

82

// функция с направлением vector

83

f = (t) => _multivariateFunction(_pointOfView + t * vector) -

 

,! _multivariateFunction(_pointOfView);

84

// вставляем её в анализатор

85

_analyzer.Function = f;

86

// рассчитываем значение вектора

87

answer[i] = _pointOfView + _analyzer.GetCoefficient() * vector;

88

// поворачиваем вектор

89

vector *= rotationMatrix;

90

}

27

91

 

92

return answer;

93

}

94

95/// <summary>

96/// Дополнительная преобразованная функция многих переменных в БМФ одной ,! переменной.

97/// </summary>

98/// <param name="t">параметр бесконечно малой</param>

99/// <returns>значение БМФ</returns>

100private double Function(double t) =>

101

_multivariateFunction(_pointOfView + t * _vector) -

 

,! _multivariateFunction(_pointOfView);

102

}

103

 

104

105

106

107

108

109

110

111

112

113

114

///<summary>

///Представляет собой вектор любой длины.

///</summary>

public class Vector

{

///<summary>

///Массив элементов вектора.

///</summary>

///<value></value>

private double[] Items { get; set; }

115

116

117

118

119

///<summary>

///Длина вектора.

///</summary>

public int Length { get => Items.Length; }

120/// <summary>

121/// Стандартный конструктор задания элементов вектора.

122/// </summary>

123/// <param name="items">элементы вектора</param>

124public Vector(params double[] items) =>

125

126

127

128

129

this.Items = items;

public override string ToString() => string.Join("\t", Items);

130/// <summary>

131/// Передаёт элемент вектора по индексу.

132/// </summary>

133/// <param name="index">индекс элемента вектора</param>

134/// <returns>элемент вектора в индексе</returns>

135public double Get(int index) => Items[index];

28

136

137/// <summary>

138/// Рассчитывает ортогональный этому вектору вектор.

139/// </summary>

140/// <remark>

141/// Реализован только для R^2.

142/// </remark>

143/// <returns>ортогональный вектор</returns>

144public Vector GetOrth() =>

145

146

new Vector(Get(1), -1 * Get(0));

147/// <summary>

148/// Определение оператора сложения векторов.

149/// </summary>

150/// <param name="left">левый вектор</param>

151/// <param name="right">правый вектор</param>

152/// <returns>сумма векторов - новый вектор</returns>

153public static Vector operator +(Vector left, Vector right)

154{

155

if (left.Length != right.Length)

156

throw new ApplicationException("для сложения векторы должны быть

 

,! одной длины");

157

 

158

int length = left.Length;

159

var answer = new double[length];

160

for (int i = 0; i < length; i++)

161

answer[i] = left.Get(i) + right.Get(i);

162

return new Vector(answer);

163

}

164

 

165/// <summary>

166/// Определение оператора разницы векторов.

167/// </summary>

168/// <param name="left">уменьшаемый вектор</param>

169/// <param name="right">вычитаемый вектор</param>

170/// <returns>разница векторов - новый вектор</returns>

171public static Vector operator -(Vector left, Vector right)

172{

173

if (left.Length != right.Length)

174

throw new ApplicationException("для вычитания векторы должны быть

 

,! одной длины");

175

int length = left.Length;

176

var answer = new double[length];

177

for (int i = 0; i < length; i++)

178

answer[i] = left.Get(i) - right.Get(i);

179

return new Vector(answer);

180

}

29

181/// <summary>

182/// Определение операции скалярного произведения векторов.

183/// </summary>

184/// <param name="left">левый вектор</param>

185/// <param name="right">правый вектор</param>

186/// <returns>скалярное произведение векторов - число</returns>

187public static double operator *(Vector left, Vector right)

188{

189

if (left.Length != right.Length)

190

throw new ApplicationException("для произведения векторы должны

 

,! быть одной длины");

191

 

192

int length = left.Length;

193

double answer = 0;

194

for (int i = 0; i < length; i++)

195

answer += left.Get(i) * right.Get(i);

196

return answer;

197

}

198

 

199/// <summary>

200/// Определение операции произведения числа на вектор.

201/// </summary>

202/// <param name="number">число</param>

203/// <param name="vector">вектор</param>

204/// <returns>произведение - новый вектор</returns>

205public static Vector operator *(double number, Vector vector)

206{

207

int length

=

vector.Length;

208

var answer

=

new double[length];

209

for (int i =

0; i < length; i++)

210

answer[i] = number * vector.Get(i);

211

return new Vector(answer);

212

}

 

 

213

214public static Vector operator *(Vector vector, Matrix matrix)

215{

216

if (vector.Length != matrix.Length)

217

throw new ApplicationException("для произведения вектор и матрица

 

,! должны быть одной длины");

218

int length =

vector.Length;

219

var answer =

new double[length];

220

for (int i =

0; i < length; i++)

221

{

 

222

answer[i] = 0;

223

for (int

j = 0; j < length; j++)

224

answer[i] += vector.Get(j) * matrix.Get(j, i);

225

}

 

30

226

return new Vector(answer);

227}

228}

229

230/// <summary>

231/// Класс, представляющий матрицу.

232///

233/// Прим.: все функции работают только с квадратными матрицами.

234/// Прим.: некоторые функции работают только с матрицей 2 на 2.

235/// </summary>

236public class Matrix

237{

238/// <summary>

239/// Разделитель элементов матрицы в строковом представлении.

240/// </summary>

241private const string ITEM_DELIMITER = ", ";

242

243/// <summary>

244/// Разделитель строк матрицы в строковом представлении.

245/// </summary>

246private const string ROW_DELIMITER = "\n";

247

248

249

250

251

252

///<summary>

///Элементы матрицы.

///</summary>

public double[][] items { get; private set; }

253/// <summary>

254/// Стандартный конструктор.

255/// </summary>

256/// <param name="items">двумерный массив элементов матрицы</param>

257public Matrix(double[][] items)

258{

259

260

261

262

263

264

265

266

267

268

269

270

271

if (items.Length != items[0].Length)

throw new ArgumentException("матрица должна быть квадратной");

this.items = items;

}

///<summary>

///Элемент матрицы в индексах.

///</summary>

///<param name="index1">столбец</param>

///<param name="index2">строка</param>

public double Get(int index1, int index2) => items[index1][index2];

272

31

273

274

275

276

277

278

///<summary>

///Длина стороны матрицы.

///</summary>

public int Length => items.Length;

279/// <summary>

280/// Переопределение преобразования в строку:

281/// все элементы через запятую, строки через перевод строки.

282/// </summary>

283public override string ToString()

284{

285

int length =

Length;

286

var arr = new string[length];

287

for (int i =

0; i < length; i++)

288

arr[i] =

String.Join(ITEM_DELIMITER, items[i]);

289

return String.Join(ROW_DELIMITER, arr);

290

}

 

291

292/// <summary>

293/// Умножение матрицы на вектор.

294/// </summary>

295/// <param name="matrix">матрица</param>

296/// <param name="vector">вектор</param>

297/// <returns>произведение - новый вектор</returns>

298public static Vector operator *(Matrix matrix, Vector vector)

299{

300

301

302

303

304

305

306

307

308

309

310

int length = vector.Length; var items = new double[length]; Vector temp;

//просто перемножаем строки на вектор,

//так как строки матрицы - такие же векторы

for (int i = 0; i < length; i++)

{

temp = new Vector(matrix.items[i]); items[i] = temp * vector;

}

311

 

312

return new Vector(items);

313

}

314

 

315/// <summary>

316/// Передаёт обратную матрицу.

317///

318/// Здесь представлена только оптимизированная версия для матрицы 2×2.

319/// </summary>

32

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

/// <returns>обратная матрице матрица</returns> public Matrix GetReversed()

{

// получаем определитель матрицы

var det = GetSmallDeterminant();

// создаём пустой двумерный массив

var matrix = new double[2][];

// заполняем первую строку по формуле matrix[0] = new double[2]; matrix[0][0] = items[1][1] / det;

matrix[0][1] = -1 * items[0][1] / det;

// заполняем вторую строку по формуле matrix[1] = new double[2]; matrix[1][0] = -1 * items[1][0] / det; matrix[1][1] = items[0][0] / det; return new Matrix(matrix);

}

338/// <summary>

339/// Считает определитель этой матрицы по оптимизированной формуле для ,! матрицы 2 на 2.

340/// </summary>

341/// <returns>определитель матрицы</returns>

342public double GetSmallDeterminant() =>

343

items[0][0] * items[1][1] - items[0][1] * items[1][0];

344

}

345

346/// <summary>

347/// Класс для отдельных математических операций.

348/// </summary>

349public static class Math

350{

351/// <summary>

352/// Рассчитывает матрицу поворота вектора на заданный угол в радианах.

353/// </summary>

354/// <param name="angle">угол в радианах</param>

355/// <returns>матрица поворота</returns>

356public static Matrix GetRotationMatrix(double angle)

357{

358

var matrixAsArray = new double[2][];

359

matrixAsArray[0]

= new double[]{Cos(angle), Sin(angle)};

360

matrixAsArray[1]

= new double[]{-1 * Sin(angle), Cos(angle)};

361

return new Matrix(matrixAsArray);

362}

363}

364}

33