├── C# └── OptimizationMethods │ ├── MathUtils │ ├── DoubleMatrix.cs │ ├── DoubleVector.cs │ ├── NumericCommon.cs │ ├── NumericUtils.cs │ ├── Slice.cs │ └── TemplateVector.cs │ ├── MultiDimensional.cs │ ├── OneDimensional.cs │ ├── OptimizationMethods.csproj │ ├── OptimizationMethods.sln │ ├── Program.cs │ ├── Simplex.cs │ └── Tests.cs ├── C++ └── OptimizationMethods │ ├── OptimizationMethods.sln │ ├── OptimizationMethods.vcxproj │ ├── OptimizationMethods.vcxproj.filters │ ├── OptimizationMethods.vcxproj.user │ ├── main.cpp │ ├── multi_dimensional.h │ ├── numerics │ ├── common.h │ ├── linalg │ │ ├── implementation.cpp │ │ ├── numeric_matrix.h │ │ ├── numeric_vector.h │ │ ├── slice.h │ │ ├── template_vector.h │ │ ├── template_vector_allocator.h │ │ └── vector_iterators.h │ ├── numeric_utils.h │ ├── numerics.h │ └── rational │ │ ├── rational.cpp │ │ └── rational.h │ ├── one_dimensional.h │ ├── simplex.h │ └── test.h ├── Java └── OptimizationMethods │ ├── .gitignore │ ├── OptimizationMethods.iml │ ├── pom.xml │ └── src │ └── main │ └── java │ ├── Main.java │ ├── MultiDimensional.java │ ├── OneDimensional.java │ ├── Simplex.java │ ├── SimplexIO.java │ ├── Tests.java │ └── mathUtils │ ├── DoubleMatrix.java │ ├── DoubleVector.java │ ├── NumericCommon.java │ ├── NumericUtils.java │ ├── PenaltyFunction.java │ ├── Slice.java │ ├── TemplateVector.java │ └── functionalInterfaces │ ├── ICombineFunction.java │ ├── IConditionFunction.java │ ├── IFillFunction.java │ ├── IForEachApplyFunction.java │ ├── IForEnumerateApplyFunction.java │ ├── IFunction1D.java │ ├── IFunctionND.java │ ├── IMapFunction.java │ └── IReduceFunction.java ├── OptimizationMethods.iml ├── Python ├── OptimizationMethods │ ├── .idea │ │ └── OptimizationMethods.iml │ ├── Resources │ │ └── sm_task.json │ ├── main.py │ └── simplex.py └── OptimizationMethodsNew │ ├── .idea │ ├── .gitignore │ ├── MOLabs.iml │ ├── inspectionProfiles │ │ ├── Project_Default.xml │ │ └── profiles_settings.xml │ ├── misc.xml │ ├── modules.xml │ └── vcs.xml │ ├── MultidimensionalMethods │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-312.pyc │ │ ├── bisect.cpython-312.pyc │ │ ├── fibonacci.cpython-312.pyc │ │ ├── golden_ratio.cpython-312.pyc │ │ ├── gradient_descent.cpython-312.pyc │ │ ├── penalty_function.cpython-312.pyc │ │ └── perCordDescend.cpython-312.pyc │ ├── bisect.py │ ├── conj_gradient.py │ ├── fibonacci.py │ ├── golden_ratio.py │ ├── gradient_descent.py │ ├── penalty_function.py │ └── perCordDescend.py │ ├── OnedimensionalMethods │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-312.pyc │ │ ├── bisect.cpython-312.pyc │ │ ├── fibonacci.cpython-312.pyc │ │ └── golden_ratio.cpython-312.pyc │ ├── bisect.py │ ├── fibonacci.py │ └── golden_ratio.py │ └── main.py ├── README.md └── info.md /C#/OptimizationMethods/MathUtils/DoubleVector.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System; 5 | 6 | namespace MathUtils 7 | { 8 | public delegate double FunctionND(DoubleVector x); 9 | public sealed class DoubleVector: TemplateVector, IEquatable 10 | { 11 | /// 12 | /// Длина вектра 13 | /// 14 | public double MagnitudeSqr => this.Reduce((accum, value) => accum += value * value); 15 | 16 | /// 17 | /// Длина вектра 18 | /// 19 | public double Magnitude => Math.Sqrt(MagnitudeSqr); 20 | 21 | /// 22 | /// Нормированый вариант вектора 23 | /// 24 | public DoubleVector Normalized 25 | { 26 | get 27 | { 28 | DoubleVector normalized = new DoubleVector(this); 29 | double inv_mag = 1.0 / Magnitude; 30 | normalized.Apply(v => v * inv_mag); 31 | return normalized; 32 | } 33 | } 34 | 35 | /// 36 | /// Нормализация вектора 37 | /// 38 | /// 39 | public DoubleVector Normalize() 40 | { 41 | double inv_mag = 1.0 / Magnitude; 42 | Apply(v => v * inv_mag); 43 | return this; 44 | } 45 | 46 | /// 47 | /// Скалярное произведение (this;other) 48 | /// 49 | /// 50 | /// (this;other) 51 | public double Dot(DoubleVector other) 52 | { 53 | if (Count != other.Count) throw new Exception("Unable DoubleVector dot multiply"); 54 | return this.Combine(other, (l, r) => l * r).Reduce((acc, v) => acc + v); 55 | } 56 | 57 | /// 58 | /// Скалярное произведение (a;b) 59 | /// 60 | /// 61 | /// 62 | /// (a;b) 63 | public static double Dot(DoubleVector left, DoubleVector right) => left.Dot(right); 64 | 65 | /// 66 | /// Строковое представление вектора 67 | /// 68 | /// 69 | public override string ToString() => $"{{{string.Join(", ", this.Map(v => v.ToString("0.000", CultureInfo.InvariantCulture)))}}}"; 70 | 71 | public bool Equals([AllowNull] DoubleVector other) => base.Equals(other); 72 | 73 | /// 74 | /// Конструктор вектора из массива 75 | /// 76 | /// 77 | public DoubleVector(): base() {} 78 | 79 | /// 80 | /// Конструктор вектора из массива 81 | /// 82 | /// 83 | public DoubleVector(params double[] args): base(args) {} 84 | 85 | /// 86 | /// Конструктор вектора по размеру и элементу по умолчанию 87 | /// 88 | /// 89 | public DoubleVector(int cap): base(cap) {} 90 | 91 | /// 92 | /// Конструктор копирования 93 | /// 94 | /// 95 | public DoubleVector(DoubleVector other): base(other) {} 96 | public DoubleVector(IEnumerable other) : base(other) { } 97 | 98 | /// 99 | /// Элементарные математические операции над векторами 100 | /// 101 | 102 | /////////////////////////// 103 | ///// Operator + ///// 104 | /////////////////////////// 105 | public static DoubleVector operator + (DoubleVector left, DoubleVector right) 106 | { 107 | if (left.Count != right.Count) throw new Exception("error:: operator + :: DoubleVectors of different dimensions"); 108 | return new DoubleVector(left.Combine(right, (l, r) => l + r)); 109 | } 110 | public static DoubleVector operator + (DoubleVector left, double right) => new DoubleVector(left.Combine(right, (l, r) => l + r)); 111 | public static DoubleVector operator + (double left, DoubleVector right) => new DoubleVector(right.Combine(left, (l, r) => r + l)); 112 | 113 | /////////////////////////// 114 | ///// Operator - ///// 115 | /////////////////////////// 116 | public static DoubleVector operator - (DoubleVector left, DoubleVector right) 117 | { 118 | if (left.Count != right.Count) throw new Exception("error:: operator - :: DoubleVectors of different dimensions"); 119 | return new DoubleVector(left.Combine(right, (l, r) => l - r)); 120 | } 121 | public static DoubleVector operator - (DoubleVector left, double right) => new DoubleVector(left.Combine(right, (l, r) => l - r)); 122 | public static DoubleVector operator - (double left, DoubleVector right) => new DoubleVector(right.Combine(left, (l, r) => r - l)); 123 | 124 | /////////////////////////// 125 | ///// Operator * ///// 126 | /////////////////////////// 127 | public static DoubleVector operator * (DoubleVector left, DoubleVector right) 128 | { 129 | if (left.Count != right.Count) throw new Exception("error :: operator * :: DoubleVectors of different dimensions"); 130 | return new DoubleVector(left.Combine(right, (l, r) => l * r)); 131 | } 132 | public static DoubleVector operator * (DoubleVector left, double right) => new DoubleVector(left.Combine(right, (l, r) => l * r)); 133 | public static DoubleVector operator * (double left, DoubleVector right) => new DoubleVector(right.Combine(left, (l, r) => r * l)); 134 | 135 | /////////////////////////// 136 | ///// Operator / ///// 137 | /////////////////////////// 138 | public static DoubleVector operator / (DoubleVector left, DoubleVector right) 139 | { 140 | if (left.Count != right.Count) throw new Exception("error :: operator / :: DoubleVectors of different dimensions"); 141 | return new DoubleVector(left.Combine(right, (l, r) => l / r)); 142 | } 143 | public static DoubleVector operator / (DoubleVector left, double right) => new DoubleVector(left.Combine(right, (l, r) => l / r)); 144 | public static DoubleVector operator / (double left, DoubleVector right) => new DoubleVector(right.Combine(left, (l, r) => r / l)); 145 | 146 | /// 147 | /// Рассчитывет единичный вектор в направлении от a до b 148 | /// 149 | /// 150 | /// 151 | /// 152 | public static DoubleVector Direction(DoubleVector left, DoubleVector right) 153 | { 154 | if (left.Count != right.Count) throw new Exception("error :: dirction :: DoubleVectors of different dimensions"); 155 | return (right - left).Normalize(); 156 | } 157 | 158 | public static double Distance(DoubleVector left, DoubleVector right) 159 | { 160 | if (left.Count != right.Count) throw new Exception("error :: dirction :: DoubleVectors of different dimensions"); 161 | return right.Combine(left, (l, r) => r - l).Reduce((accum, itеm) => accum + itеm * itеm); 162 | } 163 | 164 | /// 165 | /// Градиент скалярной функции векторного аргумента 166 | /// 167 | /// функция для которой рассчитываем градиент 168 | /// точка, где рассчитываем градиент 169 | /// шаг центрального разностного аналога 170 | /// 171 | public static DoubleVector Gradient(FunctionND func, DoubleVector x, double eps) 172 | { 173 | DoubleVector df = new DoubleVector(x.Count); 174 | for (int i = 0; i < x.Count; i++) df.PushBack(Partial(func, x, i, eps)); 175 | return df; 176 | } 177 | public static DoubleVector Gradient(FunctionND func, DoubleVector x) => Gradient(func, x, NumericCommon.NUMERIC_ACCURACY_MIDDLE); 178 | 179 | /// 180 | /// Частная производная в точке x вдоль координаты coord_index 181 | /// 182 | /// 183 | /// 184 | /// 185 | /// 186 | /// 187 | public static double Partial (FunctionND func, DoubleVector x, int coord_index, double eps) 188 | { 189 | if (x.NotInRange(coord_index)) throw new Exception("Partial derivative index out of bounds!"); 190 | x[coord_index] += eps; 191 | double f_r = func(x); 192 | x[coord_index] -= (2.0 * eps); 193 | double f_l = func(x); 194 | x[coord_index] += eps; 195 | return (f_r - f_l) / eps * 0.5; 196 | } 197 | 198 | public static double Partial(FunctionND func, DoubleVector x, int coord_index) => Partial(func, x, coord_index, NumericCommon.NUMERIC_ACCURACY_MIDDLE); 199 | 200 | public static double Partial2(FunctionND func, DoubleVector x, int coord_index_1, int coord_index_2, double eps) 201 | { 202 | if (x.NotInRange(coord_index_2)) throw new Exception("Partial derivative index out of bounds!"); 203 | x[coord_index_2] -= eps; 204 | double f_l = Partial(func, x, coord_index_1, eps); 205 | x[coord_index_2] += (2 * eps); 206 | double f_r = Partial(func, x, coord_index_1, eps); 207 | x[coord_index_2] -= eps; 208 | return (f_r - f_l) / eps * 0.5; 209 | } 210 | 211 | public static double Partial2(FunctionND func, DoubleVector x, int coord_index_1, int coord_index_2) => Partial2(func, x, coord_index_1, coord_index_2, NumericCommon.NUMERIC_ACCURACY_MIDDLE); 212 | 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /C#/OptimizationMethods/MathUtils/NumericCommon.cs: -------------------------------------------------------------------------------- 1 | namespace MathUtils 2 | { 3 | public class NumericCommon 4 | { 5 | public static readonly double PHI = 1.61803398874989484820; 6 | public static readonly double PSI = 1.0 / PHI; 7 | public static readonly double NUMERIC_ACCURACY_MIDDLE = 1e-6; 8 | public static readonly double NUMERIC_ACCURACY_LOW = 1e-3; 9 | public static readonly double NUMERIC_ACCURACY_HIGH = 1e-9; 10 | public static readonly int ZERO_ORDER_METHODS_MAX_ITERATIONS_COUNT = 1000; 11 | public static readonly int ITERATIONS_COUNT_HIGH = 1000; 12 | public static readonly int ITERATIONS_COUNT_MIDDLE = 500; 13 | public static readonly int ITERATIONS_COUNT_LOW = 100; 14 | public static bool SHOW_ZERO_ORDER_METHODS_DEBUG_LOG = false; 15 | public static bool SHOW_DEBUG_LOG = false; 16 | public static bool SHOW_SIMPLEX_DEBUG_LOG = false; 17 | public static bool SHOW_MATRIX_DEBUG_LOG = false; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /C#/OptimizationMethods/MathUtils/NumericUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System; 3 | 4 | namespace MathUtils 5 | { 6 | public static class NumericUtils 7 | { 8 | 9 | public static int Clamp(int value, int min, int max) 10 | { 11 | if (value < min) return min; 12 | if (value > max) return max; 13 | return value; 14 | } 15 | 16 | public static float Clamp(float value, float min, float max) 17 | { 18 | if (value < min) return min; 19 | if (value > max) return max; 20 | return value; 21 | } 22 | 23 | public static double Clamp(double value, double min, double max) 24 | { 25 | if (value < min) return min; 26 | if (value > max) return max; 27 | return value; 28 | } 29 | 30 | public static void Swap(ref T lhs, ref T rhs) 31 | { 32 | T temp; 33 | temp = lhs; 34 | lhs = rhs; 35 | rhs = temp; 36 | } 37 | 38 | public static double TestFunc1D(double x) 39 | { 40 | return (x - 5) * (x - 2); // min at point x = 3.5 41 | } 42 | 43 | public static double TestFunc2D(DoubleVector x) 44 | { 45 | return (x[0] - 5) * x[0] + (x[1] - 3) * x[1]; // min at point x = 2.5, y = 1.5 46 | } 47 | 48 | public static double TestFuncND(DoubleVector x) 49 | { 50 | double val = 0.0; 51 | 52 | for (int i = 0; i < x.Count; i++) val += (x[i] - i) * x[i]; 53 | 54 | return val; // min at point x_i = i/2, i from 0 to x.Size-1 55 | } 56 | 57 | public static int[] FibonacchiNumbers(int index) 58 | { 59 | if (index < 1) return new int[] { 0 }; 60 | 61 | if (index < 2) return new int[] { 0, 1 }; 62 | 63 | int[] res = new int[index]; 64 | 65 | res[0] = 0; 66 | 67 | res[1] = 1; 68 | 69 | for (int i = 2; i < index; i++) res[i] = res[i - 1] + res[i - 2]; 70 | 71 | return res; 72 | } 73 | 74 | public static void ClosestFibonacciPair(double value, ref int f_n, ref int f_n_1) 75 | { 76 | f_n = 0; 77 | f_n_1 = 0; 78 | 79 | if (value < 1) return; 80 | 81 | f_n_1 = 1; 82 | 83 | if (value < 2) return; 84 | int f_tmp; 85 | 86 | while (f_n < value) 87 | { 88 | f_tmp = f_n; 89 | f_n = f_n_1; 90 | f_n_1 += f_tmp; 91 | } 92 | } 93 | 94 | private struct Mat2 95 | { 96 | public long m00; 97 | public long m01; 98 | public long m10; 99 | public long m11; 100 | public static Mat2 Identity() => new Mat2() { m00 = 1, m01 = 0, m10 = 0, m11 = 1 }; 101 | } 102 | 103 | /// 104 | /// Конвертирует десятичную запись числа в рациональную, например, для числа 1.666 получим 1 2/3 105 | /// 106 | /// исходное число 107 | /// целые части 108 | /// числитель 109 | /// знаменатель 110 | /// максимально допустимый знаменатель 111 | public static void DecimalToRational(double value, out int rational_part, out int numerator, out int denominator, int max_den = 1000) 112 | { 113 | Mat2 m = Mat2.Identity(); 114 | 115 | long ai; 116 | 117 | double x; 118 | 119 | int sign = value >= 0 ? 1 : -1; 120 | 121 | x = Math.Abs(value); 122 | 123 | long t; 124 | 125 | while (m.m10 * (ai = (long)x) + m.m11 <= max_den) 126 | { 127 | t = m.m00 * ai + m.m01; 128 | 129 | m.m01 = m.m00; 130 | m.m00 = t; 131 | 132 | t = m.m10 * ai + m.m11; 133 | 134 | m.m11 = m.m10; 135 | m.m10 = t; 136 | 137 | if (x == (double)ai) break; // AF: division by zero 138 | 139 | x = 1 / (x - (double)ai); 140 | 141 | if (x > (double)0x7FFFFFFF) break; // AF: representation failure 142 | } 143 | 144 | if ((rational_part = (int)(m.m00 / m.m10)) != 0) 145 | { 146 | numerator = (int)(m.m00 - rational_part * m.m10); 147 | 148 | rational_part *= sign; 149 | 150 | denominator = (int)m.m10; 151 | 152 | return; 153 | } 154 | rational_part = 0; 155 | 156 | numerator = (int)(sign * m.m00); 157 | 158 | denominator = (int)m.m10; 159 | } 160 | 161 | public static string ToRationalStr(double value, bool fullRational = true) 162 | { 163 | int r_part, num, denom; 164 | DecimalToRational(value, out r_part, out num, out denom); 165 | return ToRationalStr(r_part, num, denom); 166 | } 167 | private static string ToRationalStr(int r_part, int num, int denom, bool fullRational = true) 168 | { 169 | if (num == 0) return $"{r_part}"; 170 | if (r_part == 0) return $"{num}/{denom}"; 171 | if (fullRational) return $"{(num + Math.Abs(r_part) * denom) * (r_part >= 0 ? 1 : -1)}/{denom}"; 172 | return $"{r_part} {num}/{denom}"; 173 | } 174 | 175 | 176 | public static string ToRationalStr(IEnumerable DoubleVector, bool fullRational = true) => $"{{{string.Join(", ", DoubleVector.Map(v => ToRationalStr(v, fullRational)))}}}"; 177 | 178 | public struct RationalNumber: IEquatable 179 | { 180 | private readonly int _numerator; 181 | private readonly int _denominator; 182 | private readonly int _intPart; 183 | public bool Equals(RationalNumber number) 184 | { 185 | if (number.Numerator != Numerator) return false; 186 | if (number.Denominator != Denominator) return false; 187 | if (number.IntPart != IntPart) return false; 188 | return true; 189 | } 190 | 191 | public override string ToString() => ToRationalStr(IntPart, Numerator, Denominator, false); 192 | 193 | public int Numerator => _numerator; 194 | public int Denominator => _denominator; 195 | public int IntPart => _intPart; 196 | 197 | public RationalNumber(int numerator, int denominator, int intPart) 198 | { 199 | _numerator = numerator; 200 | _denominator = denominator; 201 | _intPart = intPart; 202 | } 203 | 204 | public RationalNumber(RationalNumber other): this(other.IntPart, other.Numerator, other.Denominator){} 205 | 206 | public RationalNumber(double value) => DecimalToRational(value, out _intPart, out _numerator, out _denominator); 207 | } 208 | 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /C#/OptimizationMethods/MathUtils/Slice.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace OptimizationMethods.MathUtils 5 | { 6 | public struct Slice: IEquatable 7 | { 8 | private readonly int _end; 9 | private readonly int _begin; 10 | private readonly int _step; 11 | //exclusive index 12 | public int End => _end; 13 | //inclusive index 14 | public int Begin => _begin; 15 | public int Step => _step; 16 | public int Index(int index) => Begin + index * Step; 17 | 18 | public int Length 19 | { 20 | get 21 | { 22 | int total = Math.Abs(End - Begin); 23 | return Math.Abs(total / Step + total % Step); 24 | } 25 | } 26 | 27 | private static int CalcIndex(int index, int stride) => ((index % stride) + stride) % stride; 28 | public Slice Rebuild(int targetLength) 29 | { 30 | int begin = Begin == 0 ? 0 : CalcIndex(Begin, targetLength); 31 | int end = End == 0 ? targetLength : CalcIndex(End, targetLength); 32 | return Step > 0 ? new Slice(begin, end == 0 ? targetLength : end, Step): new Slice(end == 0 ? targetLength : end, begin, Step); 33 | } 34 | 35 | public bool Equals([AllowNull] Slice other) 36 | { 37 | if (other.Begin!= Begin) return false; 38 | if (other.End != End ) return false; 39 | if (other.Step != Step ) return false; 40 | return true; 41 | } 42 | 43 | public override string ToString() => Step == 1 ? $"{Begin}:{End}" : $"{Begin}:{End}:{Step}"; 44 | 45 | public Slice(int begin, int end) : this(begin, end, 1){} 46 | 47 | public Slice(int begin, int end, int step) 48 | { 49 | _step = step == 0 ? 1 : step; 50 | _begin = begin; 51 | _end = end; 52 | } 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /C#/OptimizationMethods/MultiDimensional.cs: -------------------------------------------------------------------------------- 1 | using MathUtils; 2 | using System; 3 | 4 | namespace OptimizationMethods 5 | { 6 | public static class MultiDimensional 7 | { 8 | //////////////////// 9 | /// Lab. work #2 /// 10 | //////////////////// 11 | public static DoubleVector BiSect(FunctionND targetFunction, DoubleVector lhs, DoubleVector rhs, double accuracy, int iterations) 12 | { 13 | DoubleVector x_c, dir; 14 | dir = DoubleVector.Direction(lhs, rhs) * accuracy; 15 | int cntr = 0; 16 | for (; cntr != iterations && DoubleVector.Distance(rhs, lhs) > 2 * accuracy; cntr++) 17 | { 18 | x_c = (rhs + lhs) * 0.5; 19 | if (targetFunction(x_c + dir) > targetFunction(x_c - dir)) 20 | rhs = x_c; 21 | else 22 | lhs = x_c; 23 | } 24 | #if DEBUG 25 | Console.WriteLine($"BiSect iterations number : {cntr}"); 26 | Console.WriteLine($"BiSect argument range : {DoubleVector.Distance(rhs, lhs)}"); 27 | #endif 28 | return (rhs + lhs) * 0.5; 29 | } 30 | public static DoubleVector BiSect(FunctionND targetFunction, DoubleVector lhs, DoubleVector rhs, double accuracy) => BiSect(targetFunction, lhs, rhs, accuracy, NumericCommon.ITERATIONS_COUNT_HIGH); 31 | public static DoubleVector BiSect(FunctionND targetFunction, DoubleVector lhs, DoubleVector rhs) => BiSect(targetFunction, lhs, rhs, NumericCommon.NUMERIC_ACCURACY_MIDDLE, NumericCommon.ITERATIONS_COUNT_HIGH); 32 | public static DoubleVector GoldenRatio(FunctionND targetFunction, DoubleVector _lhs, DoubleVector _rhs, double accuracy, int iterations) 33 | { 34 | DoubleVector lhs = new DoubleVector(_lhs); 35 | DoubleVector rhs = new DoubleVector(_rhs); 36 | DoubleVector x_l = rhs - (rhs - lhs) * NumericCommon.PSI; 37 | DoubleVector x_r = lhs + (rhs - lhs) * NumericCommon.PSI; 38 | double f_l = targetFunction(x_l); 39 | double f_r = targetFunction(x_r); 40 | int iteration = 0; 41 | for (; iteration != iterations && DoubleVector.Distance(rhs, lhs) > 2 * accuracy; iteration++) 42 | { 43 | if (f_l > f_r) 44 | { 45 | lhs = x_l; 46 | x_l = x_r; 47 | f_l = f_r; 48 | x_r = lhs + (rhs - lhs) * NumericCommon.PSI; 49 | f_r = targetFunction(x_r); 50 | } 51 | else 52 | { 53 | rhs = x_r; 54 | x_r = x_l; 55 | f_r = f_l; 56 | x_l = rhs - (rhs - lhs) * NumericCommon.PSI; 57 | f_l = targetFunction(x_l); 58 | } 59 | } 60 | #if DEBUG 61 | Console.WriteLine($"GoldenRatio iterations number : {iteration + 2}"); 62 | Console.WriteLine($"GoldenRatio argument range : {DoubleVector.Distance(rhs, lhs)}"); 63 | #endif 64 | return (rhs + lhs) * 0.5; 65 | } 66 | public static DoubleVector GoldenRatio(FunctionND targetFunction, DoubleVector lhs, DoubleVector rhs, double accuracy) => GoldenRatio(targetFunction, lhs, rhs, accuracy, NumericCommon.ITERATIONS_COUNT_HIGH); 67 | public static DoubleVector GoldenRatio(FunctionND targetFunction, DoubleVector lhs, DoubleVector rhs) => GoldenRatio(targetFunction, lhs, rhs, NumericCommon.NUMERIC_ACCURACY_MIDDLE, NumericCommon.ITERATIONS_COUNT_HIGH); 68 | public static DoubleVector Fibonacci(FunctionND targetFunction, DoubleVector _lhs, DoubleVector _rhs, double accuracy) 69 | { 70 | DoubleVector lhs = new DoubleVector(_lhs); 71 | DoubleVector rhs = new DoubleVector(_rhs); 72 | double fib_t = 0.0, fib_1 = 1.0, fib_2 = 1.0; 73 | double condition = DoubleVector.Distance(rhs, lhs) / accuracy; 74 | int iterations = 0; 75 | while (fib_2 < condition) 76 | { 77 | iterations++; 78 | fib_t = fib_1; 79 | fib_1 = fib_2; 80 | fib_2 += fib_t; 81 | } 82 | DoubleVector x_l = lhs + (rhs - lhs) * ((fib_2 - fib_1) / fib_2); 83 | DoubleVector x_r = lhs + (rhs - lhs) * (fib_1 / fib_2); 84 | 85 | double f_l = targetFunction(x_l); 86 | double f_r = targetFunction(x_r); 87 | for (int index = iterations; index > 0; index--) 88 | { 89 | fib_t = fib_2 - fib_1; 90 | fib_2 = fib_1; 91 | fib_1 = fib_t; 92 | 93 | if (f_l > f_r) 94 | { 95 | lhs = x_l; 96 | f_l = f_r; 97 | x_l = x_r; 98 | x_r = lhs + (rhs - lhs) * (fib_1 / fib_2); 99 | f_r = targetFunction(x_r); 100 | } 101 | else 102 | { 103 | rhs = x_r; 104 | x_r = x_l; 105 | f_r = f_l; 106 | x_l = lhs + (rhs - lhs) * ((fib_2 - fib_1) / fib_2); 107 | f_l = targetFunction(x_l); 108 | } 109 | } 110 | #if DEBUG 111 | Console.WriteLine($"Fibonacci iterations number : {iterations + 2}"); 112 | Console.WriteLine($"Fibonacci argument range : {DoubleVector.Distance(rhs, lhs)}"); 113 | #endif 114 | return (rhs + lhs) * 0.5; 115 | } 116 | public static DoubleVector Fibonacci(FunctionND targetFunction, DoubleVector lhs, DoubleVector rhs) => Fibonacci(targetFunction, lhs, rhs, NumericCommon.NUMERIC_ACCURACY_MIDDLE); 117 | 118 | public static DoubleVector PerCoordDescend(FunctionND targetFunction, DoubleVector xStart, double accuracy, int iterations) 119 | { 120 | DoubleVector lhs = new DoubleVector(xStart); 121 | 122 | DoubleVector rhs = new DoubleVector(xStart); 123 | 124 | double step = 1.0; 125 | 126 | double x_i, y_1, y_0; 127 | 128 | int opt_coord_n = 0, coord_id; 129 | 130 | int i = 0; 131 | 132 | for (i = 0; i < iterations; i++) 133 | { 134 | coord_id = i % lhs.Count; 135 | 136 | rhs[coord_id] -= accuracy; 137 | 138 | y_0 = targetFunction(rhs); 139 | 140 | rhs[coord_id] += 2 * accuracy; 141 | 142 | y_1 = targetFunction(rhs); 143 | 144 | rhs[coord_id] -= accuracy; 145 | 146 | rhs[coord_id] = y_0 > y_1 ? rhs[coord_id] += step : rhs[coord_id] -= step; 147 | 148 | x_i = lhs[coord_id]; 149 | 150 | rhs = BiSect(targetFunction, lhs, rhs, accuracy, iterations); 151 | 152 | lhs = new DoubleVector(rhs); 153 | 154 | if (Math.Abs(rhs[coord_id] - x_i) < accuracy) 155 | { 156 | opt_coord_n++; 157 | 158 | if (opt_coord_n == rhs.Count) 159 | { 160 | #if DEBUG 161 | Console.WriteLine($"per coord descend iterations number : {i}"); 162 | #endif 163 | return lhs; 164 | } 165 | continue; 166 | } 167 | opt_coord_n = 0; 168 | } 169 | #if DEBUG 170 | Console.WriteLine($"per coord descend iterations number : {iterations}"); 171 | #endif 172 | return lhs; 173 | } 174 | public static DoubleVector PerCoordDescend(FunctionND targetFunction, DoubleVector xStart, double accuracy) => PerCoordDescend(targetFunction, xStart, accuracy, NumericCommon.ITERATIONS_COUNT_HIGH); 175 | public static DoubleVector PerCoordDescend(FunctionND targetFunction, DoubleVector xStart) => PerCoordDescend(targetFunction, xStart, NumericCommon.NUMERIC_ACCURACY_MIDDLE, NumericCommon.ITERATIONS_COUNT_HIGH); 176 | 177 | //////////////////// 178 | /// Lab. work #3 /// 179 | //////////////////// 180 | public static DoubleVector GradientDescend(FunctionND targetFunction, DoubleVector xStart, double accuracy, int iterations) 181 | { 182 | DoubleVector x_i = new DoubleVector(xStart); 183 | 184 | DoubleVector x_i_1 = new DoubleVector(xStart); 185 | 186 | int cntr = 0; 187 | 188 | for (; cntr <= iterations; cntr++) 189 | { 190 | x_i_1 = x_i - DoubleVector.Gradient(targetFunction, x_i, accuracy); 191 | 192 | x_i_1 = BiSect(targetFunction, x_i, x_i_1, accuracy, iterations); 193 | 194 | if ((x_i_1 - x_i).Magnitude < accuracy) break; 195 | 196 | x_i = x_i_1; 197 | } 198 | #if DEBUG 199 | Console.WriteLine($"gradient descend iterations number : {cntr}"); 200 | #endif 201 | return (x_i_1 + x_i) * 0.5; 202 | } 203 | public static DoubleVector GradientDescend(FunctionND targetFunction, DoubleVector xStart, double accuracy) => GradientDescend(targetFunction, xStart, accuracy, NumericCommon.ITERATIONS_COUNT_HIGH); 204 | public static DoubleVector GradientDescend(FunctionND targetFunction, DoubleVector xStart) => GradientDescend(targetFunction, xStart, NumericCommon.NUMERIC_ACCURACY_MIDDLE, NumericCommon.ITERATIONS_COUNT_HIGH); 205 | 206 | public static DoubleVector СonjGradientDescend(FunctionND targetFunction, DoubleVector xStart, double accuracy, int iterations) 207 | { 208 | DoubleVector x_i = new DoubleVector(xStart); 209 | 210 | DoubleVector x_i_1 = new DoubleVector(xStart); 211 | 212 | DoubleVector s_i = DoubleVector.Gradient(targetFunction, xStart, accuracy) * (-1.0), s_i_1; 213 | 214 | double omega; 215 | 216 | int cntr = 0; 217 | 218 | for (; cntr <= iterations; cntr++) 219 | { 220 | x_i_1 = x_i + s_i; 221 | 222 | x_i_1 = BiSect(targetFunction, x_i, x_i_1, accuracy, iterations); 223 | 224 | if ((x_i_1 - x_i).Magnitude < accuracy) break; 225 | 226 | s_i_1 = DoubleVector.Gradient(targetFunction, x_i_1, accuracy); 227 | 228 | omega = Math.Pow((s_i_1).Magnitude, 2) / Math.Pow((s_i).Magnitude, 2); 229 | 230 | s_i = s_i * omega - s_i_1; 231 | 232 | x_i = x_i_1; 233 | } 234 | #if DEBUG 235 | Console.WriteLine($"conj gradient descend iterations number : {cntr}"); 236 | #endif 237 | return (x_i_1 + x_i) * 0.5; 238 | } 239 | public static DoubleVector СonjGradientDescend(FunctionND targetFunction, DoubleVector xStart, double accuracy) => СonjGradientDescend(targetFunction, xStart, accuracy, NumericCommon.ITERATIONS_COUNT_HIGH); 240 | public static DoubleVector СonjGradientDescend(FunctionND targetFunction, DoubleVector xStart) => СonjGradientDescend(targetFunction, xStart, NumericCommon.NUMERIC_ACCURACY_MIDDLE, NumericCommon.ITERATIONS_COUNT_HIGH); 241 | 242 | //////////////////// 243 | /// Lab. work #4 /// 244 | //////////////////// 245 | public static DoubleVector NewtoneRaphson(FunctionND targetFunction, DoubleVector xStart, double accuracy, int iterations) 246 | { 247 | DoubleVector x_i = new DoubleVector(xStart); 248 | 249 | DoubleVector x_i_1 = new DoubleVector(xStart); 250 | 251 | int cntr = 0; 252 | 253 | for (; cntr <= iterations; cntr++) 254 | { 255 | x_i_1 = x_i - DoubleMatrix.Invert(DoubleMatrix.Hessian(targetFunction, x_i, accuracy)) * DoubleVector.Gradient(targetFunction, x_i, accuracy); 256 | 257 | if ((x_i_1 - x_i).Magnitude < accuracy) break; 258 | 259 | x_i = x_i_1; 260 | } 261 | #if DEBUG 262 | Console.WriteLine($"Newtone - Raphson iterations number : {cntr}"); 263 | #endif 264 | return (x_i_1 + x_i) * 0.5; 265 | } 266 | public static DoubleVector NewtoneRaphson(FunctionND targetFunction, DoubleVector xStart, double accuracy) => NewtoneRaphson(targetFunction, xStart, accuracy, NumericCommon.ITERATIONS_COUNT_HIGH); 267 | public static DoubleVector NewtoneRaphson(FunctionND targetFunction, DoubleVector xStart) => NewtoneRaphson(targetFunction, xStart, NumericCommon.NUMERIC_ACCURACY_MIDDLE, NumericCommon.ITERATIONS_COUNT_HIGH); 268 | 269 | } 270 | } 271 | -------------------------------------------------------------------------------- /C#/OptimizationMethods/OneDimensional.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using MathUtils; 3 | 4 | namespace OptimizationMethods 5 | { 6 | public delegate double Function1D(double x); 7 | public static class OneDimensional 8 | { 9 | //////////////////// 10 | /// Lab. work #1 /// 11 | //////////////////// 12 | public static double BiSect(Function1D targetFunction, double lhs, double rhs, double accuracy, int iterations) 13 | { 14 | if (lhs > rhs) NumericUtils.Swap(ref lhs, ref rhs); 15 | int cntr = 0; 16 | for (; cntr != iterations && rhs - lhs > 2 * accuracy; cntr++) 17 | { 18 | double x_c = (rhs + lhs) * 0.5; 19 | if (targetFunction(x_c + accuracy) > targetFunction(x_c - accuracy)) 20 | rhs = x_c; 21 | else 22 | lhs = x_c; 23 | } 24 | #if DEBUG 25 | Console.WriteLine($"BiSect iterations number : {cntr}"); 26 | Console.WriteLine($"BiSect argument range : {rhs - lhs}"); 27 | #endif 28 | return (rhs + lhs) * 0.5; 29 | } 30 | public static double BiSect(Function1D targetFunction, double lhs, double rhs, double accuracy) => BiSect(targetFunction, lhs, rhs, accuracy, NumericCommon.ITERATIONS_COUNT_HIGH); 31 | public static double BiSect(Function1D targetFunction, double lhs, double rhs) => BiSect(targetFunction, lhs, rhs, NumericCommon.NUMERIC_ACCURACY_MIDDLE, NumericCommon.ITERATIONS_COUNT_HIGH); 32 | // INCORRECT!!! 33 | public static double GoldenRatio(Function1D targetFunction, double lhs, double rhs, double accuracy, int iterations) 34 | { 35 | if (lhs > rhs) NumericUtils.Swap(ref lhs, ref rhs); 36 | int iteration = 0; 37 | double x_l = rhs - (rhs - lhs) * NumericCommon.PSI; 38 | double x_r = lhs + (rhs - lhs) * NumericCommon.PSI; 39 | double f_l = targetFunction(x_l); 40 | double f_r = targetFunction(x_r); 41 | for (; iteration != iterations && rhs - lhs > 2 * accuracy; iteration++) 42 | { 43 | if (f_l > f_r) 44 | { 45 | lhs = x_l; 46 | x_l = x_r; 47 | f_l = f_r; 48 | x_r = lhs + (rhs - lhs) * NumericCommon.PSI; 49 | f_r = targetFunction(x_r); 50 | } 51 | else 52 | { 53 | rhs = x_r; 54 | x_r = x_l; 55 | f_r = f_l; 56 | x_l = rhs - (rhs - lhs) * NumericCommon.PSI; 57 | f_l = targetFunction(x_l); 58 | } 59 | } 60 | #if DEBUG 61 | Console.WriteLine($"GoldenRatio iterations number : {iteration + 2}"); 62 | Console.WriteLine($"GoldenRatio argument range : {rhs - lhs}"); 63 | #endif 64 | return (rhs + lhs) * 0.5; 65 | } 66 | public static double GoldenRatio(Function1D targetFunction, double lhs, double rhs, double accuracy) => GoldenRatio(targetFunction, lhs, rhs, accuracy, NumericCommon.ITERATIONS_COUNT_HIGH); 67 | public static double GoldenRatio(Function1D targetFunction, double lhs, double rhs) => GoldenRatio(targetFunction, lhs, rhs, NumericCommon.NUMERIC_ACCURACY_MIDDLE, NumericCommon.ITERATIONS_COUNT_HIGH); 68 | // INCORRECT!!! 69 | public static double Fibonacci(Function1D targetFunction, double lhs, double rhs, double accuracy) 70 | { 71 | if (lhs > rhs) NumericUtils.Swap(ref lhs, ref rhs); 72 | double fib_t = 0.0, fib_1 = 1.0, fib_2 = 1.0; 73 | double condition = (rhs - lhs) / accuracy; 74 | int iterations = 0; 75 | while (fib_2 < condition) 76 | { 77 | iterations++; 78 | fib_t = fib_1; 79 | fib_1 = fib_2; 80 | fib_2 += fib_t; 81 | } 82 | double x_l = lhs + (rhs - lhs) * ((fib_2 - fib_1) / fib_2); 83 | double x_r = lhs + (rhs - lhs) * (fib_1 / fib_2); 84 | double f_l = targetFunction(x_l); 85 | double f_r = targetFunction(x_r); 86 | for (int index = iterations; index > 0; index--) 87 | { 88 | fib_t = fib_2 - fib_1; 89 | fib_2 = fib_1; 90 | fib_1 = fib_t; 91 | 92 | if (f_l > f_r) 93 | { 94 | lhs = x_l; 95 | f_l = f_r; 96 | x_l = x_r; 97 | x_r = lhs + (rhs - lhs) * (fib_1 / fib_2); 98 | f_r = targetFunction(x_r); 99 | } 100 | else 101 | { 102 | rhs = x_r; 103 | x_r = x_l; 104 | f_r = f_l; 105 | x_l = lhs + (rhs - lhs) * ((fib_2 - fib_1) / fib_2); 106 | f_l = targetFunction(x_l); 107 | } 108 | } 109 | #if DEBUG 110 | Console.WriteLine($"Fibonacci iterations number : {iterations + 2}"); 111 | Console.WriteLine($"Fibonacci argument range : {rhs - lhs}"); 112 | #endif 113 | return (rhs + lhs) * 0.5; 114 | } 115 | public static double Fibonacci(Function1D targetFunction, double lhs, double rhs) => Fibonacci(targetFunction, lhs, rhs, NumericCommon.NUMERIC_ACCURACY_MIDDLE); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /C#/OptimizationMethods/OptimizationMethods.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /C#/OptimizationMethods/OptimizationMethods.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30717.126 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OptimizationMethods", "OptimizationMethods.csproj", "{1B0FEFCC-5E68-418D-89AD-C8A4E698D7ED}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {1B0FEFCC-5E68-418D-89AD-C8A4E698D7ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {1B0FEFCC-5E68-418D-89AD-C8A4E698D7ED}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {1B0FEFCC-5E68-418D-89AD-C8A4E698D7ED}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {1B0FEFCC-5E68-418D-89AD-C8A4E698D7ED}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {2E653FF6-936E-4061-A1C5-619E8586400B} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /C#/OptimizationMethods/Program.cs: -------------------------------------------------------------------------------- 1 | using MathUtils; 2 | using System; 3 | 4 | namespace OptimizationMethods 5 | { 6 | class Program 7 | { 8 | //////////////////// 9 | /// Lab. work #1 /// 10 | //////////////////// 11 | static double Testf1(double arg) => arg * (arg - 5.0); 12 | static void Lab1() 13 | { 14 | Console.WriteLine("\n////////////////////\n"); 15 | Console.WriteLine( "/// Lab. work #1 ///\n"); 16 | Console.WriteLine( "////////////////////\n\n"); 17 | 18 | double x_0 = 10.0; 19 | double x_1 = -1.0; 20 | Console.WriteLine($"x_0 = {x_0}, x_1 = {x_1}\n"); 21 | Console.WriteLine($"BiSect : {OneDimensional.BiSect (Testf1, x_0, x_1, 1e-3)}"); 22 | Console.WriteLine($"GoldenRatio : {OneDimensional.GoldenRatio(Testf1, x_0, x_1, 1e-3)}"); 23 | Console.WriteLine($"Fibonacchi : {OneDimensional.Fibonacci (Testf1, x_0, x_1, 1e-3)}\n"); 24 | } 25 | //////////////////// 26 | /// Lab. work #2 /// 27 | //////////////////// 28 | static double Testf2(DoubleVector args) => (args[0] - 2.0) * (args[0] - 2.0) + (args[1] - 2.0) * (args[1] - 2.0); 29 | static void Lab2() 30 | { 31 | Console.WriteLine("\n////////////////////\n"); 32 | Console.WriteLine( "/// Lab. work #2 ///\n"); 33 | Console.WriteLine( "////////////////////\n\n"); 34 | 35 | DoubleVector x_1 = new DoubleVector(0.0, 0.0); 36 | DoubleVector x_0 = new DoubleVector(5.0, 5.0); 37 | Console.WriteLine($"x_0 = {x_0}, x_1 = {x_1}\n"); 38 | Console.WriteLine($"BiSect : {MultiDimensional.BiSect (Testf2, x_1, x_0)}"); 39 | Console.WriteLine($"GoldenRatio : {MultiDimensional.GoldenRatio (Testf2, x_1, x_0)}" ); 40 | Console.WriteLine($"Fibonacci : {MultiDimensional.Fibonacci (Testf2, x_1, x_0)}"); 41 | Console.WriteLine($"PerCoordDescend : {MultiDimensional.PerCoordDescend (Testf2, x_1)}"); 42 | Console.WriteLine($"GradientDescend : {MultiDimensional.GradientDescend (Testf2, x_1)}" ); 43 | Console.WriteLine($"СonjGradientDescend : {MultiDimensional.СonjGradientDescend(Testf2, x_1)}" ); 44 | Console.WriteLine($"NewtoneRaphson : {MultiDimensional.NewtoneRaphson (Testf2, x_1)}\n"); 45 | } 46 | 47 | //////////////////// 48 | /// Lab. work #3 /// 49 | //////////////////// 50 | static void Lab3() 51 | { 52 | Console.WriteLine("\n////////////////////\n"); 53 | Console.WriteLine( "/// Lab. work #3 ///\n"); 54 | Console.WriteLine( "////////////////////\n\n"); 55 | 56 | DoubleVector x_1 = new DoubleVector(0.0, 0.0); 57 | DoubleVector x_0 = new DoubleVector(5.0, 5.0); 58 | Console.WriteLine($"x_0 = {x_0}, x_1 = {x_1}\n"); 59 | Console.WriteLine($"GradientDescend : {MultiDimensional.GradientDescend (Testf2, x_1)}"); 60 | Console.WriteLine($"СonjGradientDescend : {MultiDimensional.СonjGradientDescend(Testf2, x_1)}"); 61 | Console.WriteLine($"NewtoneRaphson : {MultiDimensional.NewtoneRaphson (Testf2, x_1)}\n"); 62 | } 63 | 64 | //////////////////// 65 | /// Lab. work #4 /// 66 | //////////////////// 67 | /// Пример применения функций штрафа 68 | /// Уловие 1 69 | static double Psi1(DoubleVector args) => 1.0 / (5.0 - args[0] * 2.0 + args[1] * 3.0); 70 | /// Уловие 1 71 | static double Psi2(DoubleVector args) => 1.0 / (6.0 + args[0] * 3.0 - args[1]); 72 | ///Ишем минимум функции Testf2 при условии Psi1 и Psi2(Это внутренний штраф) 73 | static double Func(DoubleVector args) => Testf2(args) + Psi2(args) + Psi1(args); 74 | static void Lab4() 75 | { 76 | Console.WriteLine("\n////////////////////\n"); 77 | Console.WriteLine( "/// Lab. work #4 ///\n"); 78 | Console.WriteLine( "////////////////////\n\n"); 79 | DoubleVector x_1 = new DoubleVector(0.0, 0.0); 80 | DoubleVector x_0 = new DoubleVector(5.0, 5.0); 81 | Console.WriteLine($"x_0 = {x_0}, x_1 = {x_1}\n"); 82 | Console.WriteLine($"NewtoneRaphson : {MultiDimensional.NewtoneRaphson(Testf2, x_1)}"); 83 | Console.WriteLine($"NewtoneRaphson : {MultiDimensional.NewtoneRaphson(Func, x_1)}\n"); 84 | } 85 | static void Main(string[] args) 86 | { 87 | Tests.TestAll(); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /C#/OptimizationMethods/Tests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System; 3 | using MathUtils; 4 | using static MathUtils.NumericUtils; 5 | 6 | namespace OptimizationMethods 7 | { 8 | public static class Tests 9 | { 10 | public static void VectorTest() 11 | { 12 | DoubleVector b = new DoubleVector(5.0, 6.0, 8.0); 13 | Console.Write("///////////////////////////////////////////\n"); 14 | Console.Write("//////// VectorTest ////////\n"); 15 | Console.Write("///////////////////////////////////////////\n"); 16 | Console.Write($"{b} + {b} = {b + b}\n"); 17 | Console.Write($"{b} - {b} = {b - b}\n"); 18 | Console.Write($"{b} / {b} = {b / b}\n"); 19 | Console.Write($"{b} * {b} = {b * b}\n"); 20 | Console.Write($"{2} + {b} = {b + 2}\n"); 21 | Console.Write($"{b} + {2} = {2 + b}\n"); 22 | Console.Write($"{2} - {b} = {2 - b}\n"); 23 | Console.Write($"{b} - {2} = {b - 2}\n"); 24 | Console.Write($"{2} * {b} = {b * 2}\n"); 25 | Console.Write($"{b} * {2} = {2 * b}\n"); 26 | Console.Write($"{2} / {b} = {NumericUtils.ToRationalStr(2 / b, false)}\n"); 27 | Console.Write($"{b} / {2} = {NumericUtils.ToRationalStr(b / 2, false)}\n"); 28 | } 29 | public static void OneDimensionalMethodsTest() 30 | { 31 | Console.WriteLine("\n///////////////////////////////////////////"); 32 | Console.WriteLine( "//////// OneDimensionalMethodsTest ////////"); 33 | Console.WriteLine( "///////////////////////////////////////////\n"); 34 | 35 | const double x_0 = 10.0; 36 | const double x_1 = -1.0; 37 | Console.WriteLine($"Search range: x_0 = {x_0}, x_1 = {x_1}"); 38 | Console.WriteLine($"BiSect : {OneDimensional.BiSect (NumericUtils.TestFunc1D, x_0, x_1, 1e-4)}"); 39 | Console.WriteLine($"GoldenRatio : {OneDimensional.GoldenRatio(NumericUtils.TestFunc1D, x_0, x_1, 1e-4)}"); 40 | Console.WriteLine($"Fibonacchi : {OneDimensional.Fibonacci (NumericUtils.TestFunc1D, x_0, x_1, 1e-4)}\n"); 41 | } 42 | public static void MultiDimensionalMethodsTest() 43 | { 44 | Console.WriteLine("\n/////////////////////////////////////////////"); 45 | Console.WriteLine( "//////// MultiDimensionalMethodsTest ////////"); 46 | Console.WriteLine( "/////////////////////////////////////////////\n"); 47 | 48 | DoubleVector x_1 = new DoubleVector(0.0, 0.0); 49 | DoubleVector x_0 = new DoubleVector(5.0, 3.0); 50 | 51 | Console.WriteLine($"x_0 = {x_0},\nx_1 = {x_1}\n") ; 52 | Console.WriteLine($"BiSect : {MultiDimensional.BiSect (NumericUtils.TestFunc2D, x_1, x_0)}"); 53 | Console.WriteLine($"GoldenRatio : {MultiDimensional.GoldenRatio (NumericUtils.TestFunc2D, x_1, x_0)}"); 54 | Console.WriteLine($"Fibonacci : {MultiDimensional.Fibonacci (NumericUtils.TestFunc2D, x_1, x_0)}"); 55 | Console.WriteLine($"PerCoordDescend : {MultiDimensional.PerCoordDescend (NumericUtils.TestFunc2D, x_1)}"); 56 | Console.WriteLine($"GradientDescend : {MultiDimensional.GradientDescend (NumericUtils.TestFunc2D, x_1)}"); 57 | Console.WriteLine($"СonjGradientDescend : {MultiDimensional.СonjGradientDescend(NumericUtils.TestFunc2D, x_1)}"); 58 | Console.WriteLine($"NewtoneRaphson : {MultiDimensional.NewtoneRaphson (NumericUtils.TestFunc2D, x_1)}\n"); 59 | } 60 | /// 61 | /// проверка работоспособности класса 62 | /// 63 | /// 64 | public static void MatrixTest() 65 | { 66 | 67 | Console.WriteLine("\n////////////////////////////"); 68 | Console.WriteLine( "//////// MatrixTest ////////"); 69 | Console.WriteLine( "////////////////////////////\n"); 70 | 71 | ///У меня всё работает, у вас мой класс тоже заработает 72 | DoubleMatrix DoubleMatrix = new DoubleMatrix(new DoubleVector(8.0, 1.0, 6.0), new DoubleVector(3.0, 5.0, 7.0), new DoubleVector(4.0, 9.0, 2.0)); 73 | Console.WriteLine(DoubleMatrix); 74 | Console.WriteLine($"\nmatrix + DoubleMatrix:\n{ DoubleMatrix + DoubleMatrix }\n"); 75 | Console.WriteLine($"\nmatrix - DoubleMatrix:\n{ DoubleMatrix - DoubleMatrix }\n"); 76 | Console.WriteLine($"\nmatrix * DoubleMatrix:\n{ DoubleMatrix * DoubleMatrix }\n"); 77 | DoubleMatrix l, u; 78 | DoubleMatrix.LU(ref DoubleMatrix, out l, out u); 79 | Console.WriteLine($"\nL DoubleMatrix:\n{l}"); 80 | Console.WriteLine($"\nU DoubleMatrix:\n{u}"); 81 | Console.WriteLine($"\nL * U - DoubleMatrix:\n{l * u - DoubleMatrix}"); 82 | DoubleVector b = new DoubleVector(1.0, 2.0, 3.0); 83 | /// x = {0.05, 0.3, 0.05}; 84 | DoubleVector x = DoubleMatrix.Linsolve(DoubleMatrix, b); 85 | Console.WriteLine($"\nx DoubleVector:\n{x}"); 86 | Console.WriteLine($"\nAx - b:\n{DoubleMatrix * x - b}"); 87 | Console.WriteLine($"\nA*inv(A):\n{DoubleMatrix / DoubleMatrix}"); 88 | DoubleMatrix matrix_ = new DoubleMatrix(new DoubleVector(8.0, 1.0, 6.0), new DoubleVector(3.0, 5.0, 7.0)); 89 | Console.WriteLine($"\nnon rect mat:\n{matrix_}"); 90 | Console.WriteLine($"\nnon rect mat mul by transposed it self :\n{matrix_ * DoubleMatrix.Transpose(matrix_)}"); 91 | DoubleMatrix m = DoubleMatrix.Hessian(NumericUtils.TestFuncND, new DoubleVector(0.0, 0.0, 0.0)); 92 | Console.WriteLine($"\nHessian(MultiDimensional.TestFuncND):\n{m}"); 93 | } 94 | public static void NumericTests() 95 | { 96 | Console.WriteLine("\n//////////////////////////////"); 97 | Console.WriteLine( "//////// NumericTests ////////"); 98 | Console.WriteLine( "//////////////////////////////\n"); 99 | double[] numbers = { 1.666, 0.666, -3.0, -0.125, 3.769, -1.666, -0.666, 3.0, 0.125, -3.769 }; 100 | foreach(double number in numbers) Console.WriteLine($"number = {number} = {new RationalNumber(number)}"); 101 | DoubleVector b = new DoubleVector(1.412, 2.33, -3.75); 102 | Console.WriteLine(b); 103 | Console.WriteLine(NumericUtils.ToRationalStr(b, false)); 104 | } 105 | 106 | public static void SimpexTest() 107 | { 108 | Console.WriteLine("\n/////////////////////////////"); 109 | Console.WriteLine( "//////// SimplexTest ////////"); 110 | Console.WriteLine( "/////////////////////////////\n"); 111 | 112 | DoubleVector b = new DoubleVector(40.0, 28.0, 14.0); 113 | DoubleVector c = new DoubleVector(2.0, 3.0); 114 | 115 | DoubleMatrix A = new DoubleMatrix 116 | ( 117 | new DoubleVector(-2.0, 6.0), 118 | new DoubleVector( 3.0, 2.0), 119 | new DoubleVector( 2.0,-1.0) 120 | ); 121 | 122 | Console.WriteLine(" f(x,c) = 2x1 + 3x2;\n arg_max = {4, 8}, f(arg_max) = 32"); 123 | Console.WriteLine(" |-2x1 + 6x2 <= 40"); 124 | Console.WriteLine(" | 3x1 + 2x2 <= 28"); 125 | Console.WriteLine(" | 2x1 - x2 <= 14\n"); 126 | 127 | Simplex sym_0 = new Simplex(A, c, new List() { Sign.Less, Sign.Less, Sign.Less }, b); 128 | sym_0.Solve(SimplexProblemType.Max); 129 | 130 | Console.WriteLine("\n f(x,c) = -2x1 + 3x2;\n arg_min = {7, 0}, f(arg_min) =-14\n"); 131 | 132 | Simplex sym_1 = new Simplex(A, new DoubleVector(-2.0, 3.0), new List() { Sign.Less, Sign.Less, Sign.Less }, b); 133 | sym_1.Solve(SimplexProblemType.Min); 134 | 135 | 136 | Console.WriteLine("/////////////////////////////"); 137 | Console.WriteLine(" f(x,c) = 2x1 + 3x2;\n arg_min = {62/5, 54/5}, f(arg_max) = 57 1/5"); 138 | Console.WriteLine(" |-2x1 + 6x2 >= 40"); 139 | Console.WriteLine(" | 3x1 + 2x2 >= 28"); 140 | Console.WriteLine(" | 2x1 - x2 >= 14\n"); 141 | Simplex sym_2 = new Simplex(A, new DoubleVector(2.0, 1.0), new List() { Sign.More, Sign.More, Sign.More }, b); 142 | sym_2.Solve(SimplexProblemType.Min); 143 | Console.WriteLine(" f(x,c) = -2x1 - x2;\n arg_min = {62/5, 54/5}, f(arg_max) = -35 3/5"); 144 | 145 | Simplex sym_3 = new Simplex(A, new DoubleVector(-2.0, -1.0), new List() { Sign.More, Sign.More, Sign.More }, b); 146 | sym_3.Solve(SimplexProblemType.Max); 147 | Console.WriteLine(" f(x,c) = 2x1 + 3x2;\n arg_min = {none, none}, f(arg_max) = none"); 148 | Simplex sym_4 = new Simplex(A, c, new List() { Sign.Equal, Sign.Equal, Sign.Equal }, b); 149 | sym_4.Solve(SimplexProblemType.Max); 150 | 151 | } 152 | 153 | public static void TestAll() 154 | { 155 | // float aaa = 123.5123f; 156 | // Console.WriteLine($"{string.Format("{0,0:F}", aaa).Replace(',', '.')}"); 157 | // NumericTests(); 158 | // OneDimensionalMethodsTest(); 159 | // MultiDimensionalMethodsTest(); 160 | VectorTest(); 161 | // MatrixTest(); 162 | // SimpexTest(); 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /C++/OptimizationMethods/OptimizationMethods.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30717.126 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OptimizationMethods", "OptimizationMethods.vcxproj", "{C3A37564-6581-4939-8978-D7F188BB0341}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {C3A37564-6581-4939-8978-D7F188BB0341}.Debug|x64.ActiveCfg = Debug|x64 17 | {C3A37564-6581-4939-8978-D7F188BB0341}.Debug|x64.Build.0 = Debug|x64 18 | {C3A37564-6581-4939-8978-D7F188BB0341}.Debug|x86.ActiveCfg = Debug|Win32 19 | {C3A37564-6581-4939-8978-D7F188BB0341}.Debug|x86.Build.0 = Debug|Win32 20 | {C3A37564-6581-4939-8978-D7F188BB0341}.Release|x64.ActiveCfg = Release|x64 21 | {C3A37564-6581-4939-8978-D7F188BB0341}.Release|x64.Build.0 = Release|x64 22 | {C3A37564-6581-4939-8978-D7F188BB0341}.Release|x86.ActiveCfg = Release|Win32 23 | {C3A37564-6581-4939-8978-D7F188BB0341}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {7DDAFB0A-8E91-4BED-B87F-2973236F6FA8} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /C++/OptimizationMethods/OptimizationMethods.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {c3a37564-6581-4939-8978-d7f188bb0341} 25 | C 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | Level3 100 | true 101 | true 102 | true 103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | true 105 | 106 | 107 | Console 108 | true 109 | true 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 118 | true 119 | stdcpp17 120 | 121 | 122 | Console 123 | true 124 | 125 | 126 | 127 | 128 | Level3 129 | true 130 | true 131 | true 132 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 133 | true 134 | 135 | 136 | Console 137 | true 138 | true 139 | true 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | -------------------------------------------------------------------------------- /C++/OptimizationMethods/OptimizationMethods.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {a7fdffa4-159e-416f-97d4-1924a42fdb0f} 18 | 19 | 20 | 21 | 22 | Исходные файлы 23 | 24 | 25 | Исходные файлы 26 | 27 | 28 | Исходные файлы 29 | 30 | 31 | 32 | 33 | Файлы заголовков 34 | 35 | 36 | Файлы заголовков 37 | 38 | 39 | Файлы заголовков 40 | 41 | 42 | Файлы заголовков 43 | 44 | 45 | Файлы заголовков 46 | 47 | 48 | Файлы заголовков 49 | 50 | 51 | NumericUtils 52 | 53 | 54 | Файлы заголовков 55 | 56 | 57 | NumericUtils 58 | 59 | 60 | NumericUtils 61 | 62 | 63 | Файлы заголовков 64 | 65 | 66 | Файлы заголовков 67 | 68 | 69 | NumericUtils 70 | 71 | 72 | Файлы заголовков 73 | 74 | 75 | Файлы заголовков 76 | 77 | 78 | Файлы заголовков 79 | 80 | 81 | -------------------------------------------------------------------------------- /C++/OptimizationMethods/OptimizationMethods.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | true 5 | 6 | -------------------------------------------------------------------------------- /C++/OptimizationMethods/main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuryStrelkov/OptimizationMethods/745af24e1c78df1e600e5f87423bf7f3d3ceaf8b/C++/OptimizationMethods/main.cpp -------------------------------------------------------------------------------- /C++/OptimizationMethods/multi_dimensional.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "numerics/numerics.h" 3 | 4 | typedef F64(*function_nd)(const numerics::vector_f64&); 5 | static numerics::vector_f64 bisect (function_nd function, const numerics::vector_f64& left, const numerics::vector_f64& right, const F64 eps = N_DIM_ACCURACY, const I32 max_iterations = N_DIM_ITERS_MAX); 6 | static numerics::vector_f64 golden_ratio(function_nd function, const numerics::vector_f64& left, const numerics::vector_f64& right, const F64 eps = N_DIM_ACCURACY, const I32 max_iters = N_DIM_ITERS_MAX); 7 | static numerics::vector_f64 fibonacci (function_nd function, const numerics::vector_f64& left, const numerics::vector_f64& right, const F64 eps = N_DIM_ACCURACY); 8 | 9 | static numerics::vector_f64 per_coord_descend (function_nd function, const numerics::vector_f64& x_start, const F64 eps = N_DIM_ACCURACY, const I32 max_iters = N_DIM_ITERS_MAX); 10 | static numerics::vector_f64 gradient_descend (function_nd function, const numerics::vector_f64& x_start, const F64 eps = N_DIM_ACCURACY, const I32 max_iters = N_DIM_ITERS_MAX); 11 | static numerics::vector_f64 conj_gradient_descend(function_nd function, const numerics::vector_f64& x_start, const F64 eps = N_DIM_ACCURACY, const I32 max_iters = N_DIM_ITERS_MAX); 12 | static numerics::vector_f64 newtone_raphson (function_nd function, const numerics::vector_f64& x_start, const F64 eps = N_DIM_ACCURACY, const I32 max_iters = N_DIM_ITERS_MAX); 13 | 14 | 15 | // Ìåòîäû n-ìåðíîé äèõîòîìèè, çîëîòîãî ñå÷åíèÿ è Ôèáîíà÷÷è îïðåäåëÿþò ìèíèìóì ñòðîãî âäîëü íàïðàâëåíèÿ èç x_0 â x_1 16 | // ò.å., åñëè èñòèííûé ìèíèìóì ôóíêöèè íà ýòîì íàïðàâëåíèè íå ëåæèò, ìåòîä âñ¸ ðàâíî íàéä¸ò ìèíèìàëüíîå çíà÷åíèå, íî îíî 17 | // áóäåò îòëè÷àòüñÿ îò èñòèííîãî ìèíèìóìà 18 | static numerics::vector_f64 bisect(function_nd function, const numerics::vector_f64& left, const numerics::vector_f64& right, const F64 eps, const I32 max_iterations) 19 | { 20 | numerics::vector_f64 x_c, dir, lhs(left), rhs(right); 21 | dir = numerics::vector_f64::direction(lhs, rhs) * eps; 22 | I32 iteration = 0; 23 | for (; iteration != max_iterations && numerics::vector_f64::distance(lhs, rhs) > 2 * eps; iteration++) 24 | { 25 | x_c = (lhs + rhs) * 0.5; 26 | if (function(x_c - dir) > function(x_c + dir)) 27 | lhs = x_c; 28 | else 29 | rhs = x_c; 30 | } 31 | #if _DEBUG 32 | std::cout << "bisect::function arg range : " << (rhs - lhs).magnitude() << "\n"; 33 | std::cout << "bisect::function probes count : " << iteration * 2 << "\n"; 34 | #endif 35 | return (lhs + rhs) * 0.5; 36 | } 37 | 38 | static numerics::vector_f64 golden_ratio(function_nd function, const numerics::vector_f64& left, const numerics::vector_f64& right, const F64 eps, const I32 max_iterations) 39 | { 40 | numerics::vector_f64 lhs(left), rhs(right); 41 | I32 iteration = 0; 42 | numerics::vector_f64 x_l = rhs - (rhs - lhs) * PSI; 43 | numerics::vector_f64 x_r = lhs + (rhs - lhs) * PSI; 44 | F64 f_l = function(x_l); 45 | F64 f_r = function(x_r); 46 | for (; iteration != max_iterations && numerics::vector_f64::distance(lhs, rhs) > 2 * eps; iteration++) 47 | { 48 | if (f_l > f_r) 49 | { 50 | lhs = x_l; 51 | x_l = x_r; 52 | f_l = f_r; 53 | x_r = lhs + (rhs - lhs) * PSI; 54 | f_r = function(x_r); 55 | } 56 | else 57 | { 58 | rhs = x_r; 59 | x_r = x_l; 60 | f_r = f_l; 61 | x_l = rhs - (rhs - lhs) * PSI; 62 | f_l = function(x_l); 63 | } 64 | } 65 | #if _DEBUG 66 | std::cout << "golden_ratio::function arg range : " << (rhs - lhs).magnitude() << "\n"; 67 | std::cout << "golden_ratio::function probes count : " << iteration + 2 << "\n"; 68 | #endif 69 | return (right + left) * 0.5; 70 | } 71 | 72 | static numerics::vector_f64 fibonacci(function_nd function, const numerics::vector_f64& left, const numerics::vector_f64& right, const F64 eps) 73 | { 74 | numerics::vector_f64 lhs(left), rhs(right); 75 | F64 condition = numerics::vector_f64::distance(lhs, rhs) / eps; 76 | F64 fib_t{ 0.0 }, fib_1{ 1.0 }, fib_2{ 1.0 }; 77 | I32 iterations{ 0 }; 78 | while (fib_2 < condition) 79 | { 80 | iterations++; 81 | fib_t = fib_1; 82 | fib_1 = fib_2; 83 | fib_2 += fib_t; 84 | } 85 | numerics::vector_f64 x_l = lhs + (rhs - lhs) * ((fib_2 - fib_1) / fib_2); 86 | numerics::vector_f64 x_r = lhs + (rhs - lhs) * (fib_1 / fib_2); 87 | F64 f_l = function(x_l); 88 | F64 f_r = function(x_r); 89 | for (I32 index = iterations; index > 0; index--) 90 | { 91 | fib_t = fib_2 - fib_1; 92 | fib_2 = fib_1; 93 | fib_1 = fib_t; 94 | if (f_l > f_r) 95 | { 96 | lhs = x_l; 97 | f_l = f_r; 98 | x_l = x_r; 99 | x_r = lhs + (rhs - lhs) * (fib_1 / fib_2); 100 | f_r = function(x_r); 101 | } 102 | else 103 | { 104 | rhs = x_r; 105 | x_r = x_l; 106 | f_r = f_l; 107 | x_l = lhs + (rhs - lhs) * ((fib_2 - fib_1) / fib_2); 108 | f_l = function(x_l); 109 | } 110 | // #if _DEBUG 111 | // std::cout << "\nfibonacchi [a, b] range: " << (right - left) << "\n"; 112 | // #endif 113 | } 114 | #if _DEBUG 115 | std::cout << "fibonacci::function arg range : " << (rhs - lhs).magnitude() << "\n"; 116 | std::cout << "fibonacci::function probes count : " << iterations + 2 << "\n"; 117 | #endif 118 | return (rhs + lhs) * 0.5; 119 | } 120 | 121 | // Ïîêîîðäèíàòíûé ñïóñê, ãðàäèåíòíûé ñïóñê è ñïóñê ñ ïîìîùüþ ñîïðÿæ¸ííûõ ãðàäèåíòîâ, îïðåäåëÿþò 122 | // ìèíèìàëüíîå çíà÷åíèå ôóíêöèè òîëüêî ïî îäíîé íà÷àëüíîé òî÷êå x_start. 123 | // Ïîýòîìó íå çàâèñÿò îò âûáîðà íàïðàâëåíèÿ. 124 | static numerics::vector_f64 per_coord_descend(function_nd function, const numerics::vector_f64& x_start, const F64 eps, const I32 max_iters) 125 | { 126 | numerics::vector_f64 x_0(x_start); 127 | numerics::vector_f64 x_1(x_start); 128 | F64 step = 1.0; 129 | F64 x_i, y_1, y_0; 130 | I32 opt_coord_n = 0, coord_id; 131 | for (I32 i = 0; i < max_iters; i++) 132 | { 133 | coord_id = i % x_0.size(); 134 | x_1[coord_id] -= eps; 135 | y_0 = function(x_1); 136 | x_1[coord_id] += 2.0 * eps; 137 | y_1 = function(x_1); 138 | x_1[coord_id] -= eps; 139 | x_1[coord_id] = y_0 > y_1 ? x_1[coord_id] += step : x_1[coord_id] -= step; 140 | x_i = x_0[coord_id]; 141 | x_1 = fibonacci(function, x_0, x_1, eps); 142 | x_0 = x_1; 143 | if (std::abs(x_1[coord_id] - x_i) < 2 * eps) 144 | { 145 | opt_coord_n++; 146 | 147 | if (opt_coord_n == x_1.size()) 148 | { 149 | #if DISPLAY_PROGRES 150 | std::cout << "\nper coord descend iterations number : " << i << "\n"; 151 | #endif 152 | return x_0; 153 | } 154 | continue; 155 | } 156 | opt_coord_n = 0; 157 | } 158 | #if DISPLAY_PROGRES 159 | std::cout << "per coord descend iterations number : " << max_iters << "\n"; 160 | #endif 161 | return x_0; 162 | } 163 | 164 | static numerics::vector_f64 gradient_descend(function_nd function, const numerics::vector_f64& x_start, const F64 eps, const I32 max_iters) 165 | { 166 | numerics::vector_f64 x_i(x_start); 167 | numerics::vector_f64 x_i_1; 168 | numerics::vector_f64 grad; 169 | I32 cntr = 0; 170 | for(; cntr <= max_iters; cntr++) 171 | { 172 | grad = numerics::vector_f64::gradient(function, x_i, eps); 173 | x_i_1 = x_i - grad; 174 | x_i_1 = fibonacci(function, x_i, x_i_1, eps); 175 | if (numerics::vector_f64::distance(x_i_1, x_i) < 2 * eps) break; 176 | x_i = x_i_1; 177 | } 178 | #if DISPLAY_PROGRES 179 | std::cout << "\ngradient descend iterations number : " << cntr << "\n"; 180 | #endif 181 | return (x_i_1 + x_i) * 0.5; 182 | } 183 | 184 | static numerics::vector_f64 conj_gradient_descend(function_nd function, const numerics::vector_f64& x_start, const F64 eps, const I32 max_iters) 185 | { 186 | numerics::vector_f64 x_i(x_start); 187 | numerics::vector_f64 x_i_1; 188 | numerics::vector_f64 s_i = numerics::vector_f64::gradient(function, x_i, eps)*(-1.0), s_i_1; 189 | F64 omega; 190 | I32 cntr = 0; 191 | for (; cntr <= max_iters; cntr++) 192 | { 193 | x_i_1 = x_i + s_i; 194 | if (numerics::vector_f64::distance(x_i_1, x_i) < 2 * eps) break; 195 | x_i_1 = fibonacci(function, x_i, x_i_1, eps); 196 | s_i_1 = numerics::vector_f64::gradient(function, x_i_1, eps); 197 | omega = std::pow(s_i_1.magnitude(), 2) / std::pow(s_i.magnitude(), 2); 198 | s_i = s_i * omega - s_i_1; 199 | x_i = x_i_1; 200 | } 201 | #if DISPLAY_PROGRES 202 | std::cout << "\nconj gradient descend iterations number : " << cntr << "\n"; 203 | #endif 204 | return (x_i_1 + x_i) * 0.5; 205 | } 206 | 207 | static numerics::vector_f64 newtone_raphson (function_nd function, const numerics::vector_f64& x_start, const F64 eps, const I32 max_iters) 208 | { 209 | numerics::vector_f64 x_i(x_start); 210 | numerics::vector_f64 x_i_1; 211 | numerics::vector_f64 grad ; 212 | numerics::matrix_f64 hess(1, 1); 213 | I32 cntr = 0; 214 | for (; cntr <= max_iters; cntr++) 215 | { 216 | grad = numerics::vector_f64::gradient(function, x_i, eps); 217 | hess = numerics::matrix_f64::invert(numerics::matrix_f64::hessian(function, x_i, eps)); 218 | x_i_1 = x_i - (hess * grad); 219 | if (numerics::vector_f64::distance(x_i_1, x_i) < 2 * eps) break; 220 | x_i = x_i_1; 221 | } 222 | #if DISPLAY_PROGRES 223 | std::cout << "\nNewtone-Raphson method iterations number : " << cntr << "\n"; 224 | #endif 225 | return (x_i_1 + x_i) * 0.5; 226 | } 227 | -------------------------------------------------------------------------------- /C++/OptimizationMethods/numerics/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #if defined(__APPLE__) 10 | // copy from STL lib/may be unsafe... 11 | template 12 | _Ty exchange(_Ty& _Val, _Other&& _New_val) noexcept /* strengthened */ { 13 | // assign _New_val to _Val, return previous _Val 14 | _Ty _Old_val = static_cast<_Ty&&>(_Val); 15 | _Val = static_cast<_Other&&>(_New_val); 16 | return _Old_val; 17 | } 18 | #elif defined(__unix__) 19 | #if defined(__linux__) 20 | #define EXCHANGE std::__exchange 21 | #endif 22 | #elif defined(_WIN32) || defined(_WIN64) 23 | #define EXCHANGE std::exchange 24 | #else 25 | #error "Unknown operating system" 26 | #endif 27 | 28 | #define PHI 1.61803398874989484820 29 | #define PSI 0.61803398874989484820 30 | typedef uint8_t UI8; 31 | typedef uint16_t UI16; 32 | typedef uint32_t UI32; 33 | typedef uint64_t UI64; 34 | 35 | typedef int8_t I8; 36 | typedef int16_t I16; 37 | typedef int32_t I32; 38 | typedef int64_t I64; 39 | 40 | typedef double F64; 41 | typedef float F32; 42 | #define DOUBLE_PRECISION 1 43 | #define N_DIM_ACCURACY 1e-5 44 | #define N_DIM_DERIVATIVE_STEP 1e-6 45 | #define N_DIM_ITERS_MAX 1000 46 | #define ACCURACY 1e-5 47 | #define ITERS_MAX 50 48 | #define MAX_DENOMINATOR 1000 49 | #define NUMBER_CHARS_COUNT 11 50 | #define DECIMAL_NUMBERS_REPRESNTATION 0 51 | #define RATIONAL_NUMBERS_REPRESNTATION (!DECIMAL_NUMBERS_REPRESNTATION) 52 | #define MAX(A, B) (A > B ? A : B) 53 | #define MIN(A, B) (A < B ? A : B) 54 | #define DISPLAY_PROGRES (_DEBUG? 1 : 0) 55 | #define NUMERICS_NAMESPACE_BEGIN namespace numerics { 56 | #define NUMERICS_NAMESPACE_END } 57 | #define STR char* 58 | #define CSTR const char* 59 | #define TRUE 1 60 | #define FALSE 0 61 | static auto sum_f = [](const auto& lhs, const auto& rhs) { return lhs + rhs; }; 62 | static auto dif_f = [](const auto& lhs, const auto& rhs) { return lhs - rhs; }; 63 | static auto div_f = [](const auto& lhs, const auto& rhs) { return lhs / rhs; }; 64 | static auto mul_f = [](const auto& lhs, const auto& rhs) { return lhs * rhs; }; 65 | 66 | #define FORMATTED_STRING_BUFFER_SIZE 2048 67 | template 68 | CSTR fstring(CSTR formatter, Args... args) { 69 | static char FORMATTED_STRING_BUFFER[FORMATTED_STRING_BUFFER_SIZE]; 70 | sprintf_s(FORMATTED_STRING_BUFFER, FORMATTED_STRING_BUFFER_SIZE, formatter, args...); 71 | return FORMATTED_STRING_BUFFER; 72 | } -------------------------------------------------------------------------------- /C++/OptimizationMethods/numerics/linalg/implementation.cpp: -------------------------------------------------------------------------------- 1 | #include "numeric_matrix.h" 2 | #include "numeric_vector.h" 3 | #include "slice.h" 4 | #include "../rational/rational.h" 5 | NUMERICS_NAMESPACE_BEGIN 6 | std::ostream& operator<<(std::ostream& stream, const slice& slice) 7 | { 8 | if (slice.step() != 1) 9 | stream << slice.begin() << ":" << slice.end() << ":" << slice.step(); 10 | else 11 | stream << slice.begin() << ":" << slice.end(); 12 | return stream; 13 | }; 14 | 15 | void template_vector_test() 16 | { 17 | auto first = template_vector_(); 18 | first.push_back(11).push_back(22).push_back(33).push_back(44).push_back(55); 19 | 20 | map_values int_to_double = first.map([](const I32& i) { return std::sqrt(i); }); 21 | 22 | for (auto const a : int_to_double) std::cout << "ccc: " << a << "\n"; 23 | 24 | auto second = template_vector_(int_to_double); 25 | 26 | auto copy_first = template_vector_(int_to_double); 27 | 28 | copy_first.push_back(11). 29 | push_back(22). 30 | push_back(33). 31 | push_back(55); 32 | 33 | auto copy_of_first = template_vector_(second); 34 | 35 | auto zip_vals = zip_values(copy_of_first.values(), copy_of_first.values()); 36 | 37 | auto diff = [](const double& a, const double& b) { return a - b; }; 38 | auto summ = [](const double& a, const double& b) { return a + b; }; 39 | 40 | // combine_values combine_vals = combine_values(zip_values(copy_of_first.values(), copy_of_first.values()), summ); combine_values combine_vals = combine_values(zip_values(copy_of_first.values(), copy_of_first.values()), summ); 41 | // combine_values combine_vals = combine_values(copy_of_first.values(), copy_of_first.values(), summ); 42 | combine_values combine_vals = combine_values(100000.0, copy_of_first.values(), summ); 43 | //combine_values combine_vals = combine_values(zip_values(copy_of_first.values(), copy_of_first.values()), summ); 44 | 45 | template_vector_ combines = template_vector_(combine_vals); 46 | 47 | std::cout << "first :" << first << "\n"; 48 | std::cout << "copy_first :" << copy_first << "\n"; 49 | std::cout << "copy_of_first :" << copy_of_first << "\n"; 50 | std::cout << "combines :" << combines << "\n"; 51 | std::cout << "combines :" << template_vector_(combines.combine(combines, diff)) << "\n"; 52 | std::cout << "first.insert(0, 13) :" << first.insert(0, 13) << "\n"; 53 | std::cout << "first.insert(2, 13) :" << first.insert(2, 13) << "\n"; 54 | std::cout << "first.insert(13,13) :" << first.insert(13, 13) << "\n"; 55 | 56 | std::cout << "first.remove_at(0) :" << first.remove_at(0) << "\n"; 57 | std::cout << "first.remove_at(2) :" << first.remove_at(2) << "\n"; 58 | std::cout << "first.remove_at(1) :" << first.remove_at(1) << "\n"; 59 | std::cout << "copy_first :" << copy_first << "\n"; 60 | auto val = copy_first[slice(3, 6)]; 61 | std::cout << "copy_first[slice(3, 6)]:" << val << "\n"; 62 | // copy_first[slice(3, 6)] = template_vector_({ 0, 0, 0 }); 63 | auto v = copy_first[slice(3, 6)]; 64 | v.apply([](const double v) {return -1.0; }); 65 | std::cout << "copy_first[slice(3, 6)]:" << copy_first[slice(3, 6)] << "\n"; 66 | std::cout << "copy_first :" << copy_first << "\n"; 67 | } 68 | 69 | void numeric_vector_test() 70 | { 71 | vector_f64 lhs({ 1.0, 2.0, 3.0, 4.0, 9.0, 8.0, 7.0, 6.0 }); 72 | vector_f64 rhs({ 9.0, 8.0, 7.0, 6.0, 1.0, 2.0, 3.0, 4.0 }); 73 | // rhs.push_back(9.0).push_back(8.0).push_back(7.0).push_back(6.0); 74 | std::cout << "lhs : " << lhs << "\n"; 75 | std::cout << "rhs : " << rhs << "\n"; 76 | std::cout << "rhs - copy : " << vector_f64(rhs) << "\n"; 77 | std::cout << "lhs + rhs : " << lhs + rhs << "\n"; 78 | std::cout << "lhs - rhs : " << lhs - rhs << "\n"; 79 | std::cout << "lhs * rhs : " << lhs * rhs << "\n"; 80 | std::cout << "lhs / rhs : " << lhs / rhs << "\n"; 81 | 82 | std::cout << "2 + rhs : " << 2.0 + rhs << "\n"; 83 | std::cout << "2 - rhs : " << 2.0 - rhs << "\n"; 84 | std::cout << "2 * rhs : " << 2.0 * rhs << "\n"; 85 | std::cout << "2 / rhs : " << 2.0 / rhs << "\n"; 86 | 87 | std::cout << "rhs + 2 : " << rhs + 2.0 << "\n"; 88 | std::cout << "rhs - 2 : " << rhs - 2.0 << "\n"; 89 | std::cout << "rhs * 2 : " << rhs * 2.0 << "\n"; 90 | std::cout << "rhs / 2 : " << rhs / 2.0 << "\n"; 91 | 92 | std::cout << "lhs += rhs : " << (lhs += rhs) << "\n"; 93 | std::cout << "lhs -= rhs : " << (lhs -= rhs) << "\n"; 94 | std::cout << "lhs *= rhs : " << (lhs *= rhs) << "\n"; 95 | std::cout << "lhs /= rhs : " << (lhs /= rhs) << "\n"; 96 | 97 | std::cout << "lhs += 2.0 : " << (lhs += 2.0) << "\n"; 98 | std::cout << "lhs -= 2.0 : " << (lhs -= 2.0) << "\n"; 99 | std::cout << "lhs *= 2.0 : " << (lhs *= 2.0) << "\n"; 100 | std::cout << "lhs /= 2.0 : " << (lhs /= 2.0) << "\n"; 101 | std::cout << "mag(lhs) : " << rational_number(lhs.magnitude()) << "\n"; 102 | std::cout << "dot(lhs, rhs) : " << rational_number(vector_f64::dot(lhs, rhs)) << "\n"; 103 | std::cout << "dir(lhs, rhs) : " << vector_f64::direction(lhs, rhs) << "\n"; 104 | std::cout << "normalized(lhs): " << lhs.normalized() << "\n"; 105 | std::cout << "normalize (lhs): " << lhs.normalize() << "\n"; 106 | std::cout << "gradient (lhs): " << vector_f64::gradient(test_f, lhs, 1e-9) << "\n"; 107 | std::cout << "partial2 (lhs): " << rational_number(vector_f64::partial2(test_f, lhs, 0, 0, 1e-9)) << "\n"; 108 | std::cout << "lhs == rhs : " << (lhs == rhs) << "\n"; 109 | std::cout << "lhs != rhs : " << (lhs != rhs) << "\n"; 110 | std::cout << "lhs > rhs : " << (lhs > rhs) << "\n"; 111 | std::cout << "lhs < rhs : " << (lhs < rhs) << "\n"; 112 | std::cout << "lhs >= rhs : " << (lhs >= rhs) << "\n"; 113 | std::cout << "lhs <= rhs : " << (lhs <= rhs) << "\n"; 114 | std::cout << "lhs >= 100 : " << (lhs >= 100.0) << "\n"; 115 | std::cout << "lhs <= 100 : " << (lhs <= 100.0) << "\n"; 116 | std::cout << "lhs : " << lhs << "\n"; 117 | lhs[slice(3, 6)] = vector_f64({ 13.0, 13.0, 13.0 }); 118 | std::cout << "lhs : " << lhs << "\n"; 119 | } 120 | 121 | void numeric_matrix_test() 122 | { 123 | vector_f64 vec({ 1.0, 2.0, 3.0 }); 124 | 125 | matrix_f64 lhs({ 8.0, 1.0, 6.0, 126 | 3.0, 5.0, 7.0, 127 | 4.0, 9.0, 2.0 }, 3, 3); 128 | 129 | matrix_f64 rhs({ 2.0, 9.0, 4.0, 130 | 7.0, 5.0, 3.0 , 131 | 6.0, 1.0, 8.0 }, 3, 3); 132 | // rhs.push_back(9.0).push_back(8.0).push_back(7.0).push_back(6.0); 133 | std::cout << "Test matrices\n"; 134 | std::cout << "lhs :\n" << lhs << "\n"; 135 | std::cout << "rhs :\n" << rhs << "\n"; 136 | std::cout << "vec :" << vec << "\n"; 137 | std::cout << "rhs * vec :\n" << rhs * vec << "\n"; 138 | std::cout << "vec * rhs :\n" << vec * rhs << "\n"; 139 | 140 | std::cout << "==========================================\n"; 141 | std::cout << "rhs[:,0] :\n" << rhs.get_col(0) << "\n"; 142 | std::cout << "rhs[:,1] :\n" << rhs.get_col(1) << "\n"; 143 | std::cout << "rhs[:,2] :\n" << rhs.get_col(2) << "\n"; 144 | std::cout << "==========================================\n"; 145 | std::cout << "rhs[0,:] :\n" << rhs.get_row(0) << "\n"; 146 | std::cout << "rhs[1,:] :\n" << rhs.get_row(1) << "\n"; 147 | std::cout << "rhs[2,:] :\n" << rhs.get_row(2) << "\n"; 148 | std::cout << "==========================================\n"; 149 | std::cout << "rhs[:,0] :\n" << rhs.get_col(0) << "\n"; 150 | std::cout << "rhs[:,1] :\n" << rhs.get_col(1) << "\n"; 151 | std::cout << "rhs[:,2] :\n" << rhs.get_col(2) << "\n"; 152 | for (auto v : rhs.cols()) 153 | { 154 | std::cout << v << " "; 155 | } 156 | std::cout << "\n==========================================\n"; 157 | std::cout << "rhs[0,:] :\n" << rhs.get_row(0) << "\n"; 158 | std::cout << "rhs[1,:] :\n" << rhs.get_row(1) << "\n"; 159 | std::cout << "rhs[2,:] :\n" << rhs.get_row(2) << "\n"; 160 | for (auto const& v : rhs.rows()) 161 | { 162 | std::cout << v << " "; 163 | } 164 | // std::cout << "rhs - copy:\n" << matrix_f64(rhs) << "\n"; 165 | std::cout << "\nOperations +,-,*,/ for matrix and matrix\n"; 166 | std::cout << "lhs + rhs :\n" << lhs + rhs << "\n"; 167 | std::cout << "lhs - rhs :\n" << lhs - rhs << "\n"; 168 | std::cout << "lhs * rhs :\n" << lhs * rhs << "\n"; 169 | std::cout << "lhs / rhs :\n" << lhs / lhs << "\n"; 170 | 171 | matrix_f64 low(1, 1), up(1, 1); 172 | matrix_f64::lu(lhs, low, up); 173 | std::cout << "LU decomposition\n"; 174 | std::cout << "low(lhs) :\n" << low << "\n"; 175 | std::cout << "up (lhs) :\n" << up << "\n"; 176 | 177 | std::cout << "Operations +,-,*,/ for number and matrix\n"; 178 | // 179 | std::cout << "2 + rhs :\n" << 2.0 + rhs << "\n"; 180 | std::cout << "2 - rhs :\n" << 2.0 - rhs << "\n"; 181 | std::cout << "2 * rhs :\n" << 2.0 * rhs << "\n"; 182 | std::cout << "2 / rhs :\n" << 2.0 / rhs << "\n"; 183 | 184 | std::cout << "Operations +,-,*,/ for matrix and number\n"; 185 | // 186 | std::cout << "rhs + 2 :\n" << rhs + 2.0 << "\n"; 187 | std::cout << "rhs - 2 :\n" << rhs - 2.0 << "\n"; 188 | std::cout << "rhs * 2 :\n" << rhs * 2.0 << "\n"; 189 | std::cout << "rhs / 2 :\n" << rhs / 2.0 << "\n"; 190 | // 191 | std::cout << "Operations +=,-=,*=,/= for matrix and matrix\n"; 192 | std::cout << "lhs += rhs:\n" << (lhs += rhs) << "\n"; 193 | std::cout << "lhs -= rhs:\n" << (lhs -= rhs) << "\n"; 194 | std::cout << "lhs *= rhs:\n" << (lhs *= rhs) << "\n"; 195 | std::cout << "lhs /= rhs:\n" << (lhs /= lhs) << "\n"; 196 | // 197 | std::cout << "Operations +=,-=,*=,/= for matrix and number\n"; 198 | std::cout << "lhs += 2.0:\n" << (lhs += 2.0) << "\n"; 199 | std::cout << "lhs -= 2.0:\n" << (lhs -= 2.0) << "\n"; 200 | std::cout << "lhs *= 2.0:\n" << (lhs *= 2.0) << "\n"; 201 | std::cout << "lhs /= 2.0:\n" << (lhs /= 2.0) << "\n"; 202 | 203 | std::cout << "lhs == rhs : " << (lhs == rhs) << "\n"; 204 | std::cout << "lhs != rhs : " << (lhs != rhs) << "\n"; 205 | std::cout << "lhs > rhs : " << (lhs > rhs) << "\n"; 206 | std::cout << "lhs < rhs : " << (lhs < rhs) << "\n"; 207 | std::cout << "lhs >= rhs : " << (lhs >= rhs) << "\n"; 208 | std::cout << "lhs <= rhs : " << (lhs <= rhs) << "\n"; 209 | std::cout << "lhs >= 100 : " << (lhs >= 100.0) << "\n"; 210 | std::cout << "lhs <= 100 : " << (lhs <= 100.0) << "\n"; 211 | std::cout << "lhs :\n" << lhs << "\n"; 212 | //lhs[slice(3, 6)] = vector_f64({ 13.0, 13.0, 13.0 }); 213 | std::cout << "lhs :\n" << lhs << "\n"; 214 | matrix_f64 big_mat = 215 | matrix_f64({ 0.8147, 0.4218, 0.2769, 0.7094, 0.8909, 0.3517, 0.5688, 0.2290, 0.2599, 0.4018, 0.7803, 0.6491, 0.4868, 0.6225, 0.9049, 0.0855, 216 | 0.9058, 0.9157, 0.0462, 0.7547, 0.9593, 0.8308, 0.4694, 0.9133, 0.8001, 0.0760, 0.3897, 0.7317, 0.4359, 0.5870, 0.9797, 0.2625, 217 | 0.1270, 0.7922, 0.0971, 0.2760, 0.5472, 0.5853, 0.0119, 0.1524, 0.4314, 0.2399, 0.2417, 0.6477, 0.4468, 0.2077, 0.4389, 0.8010, 218 | 0.9134, 0.9595, 0.8235, 0.6797, 0.1386, 0.5497, 0.3371, 0.8258, 0.9106, 0.1233, 0.4039, 0.4509, 0.3063, 0.3012, 0.1111, 0.0292, 219 | 0.6324, 0.6557, 0.6948, 0.6551, 0.1493, 0.9172, 0.1622, 0.5383, 0.1818, 0.1839, 0.0965, 0.5470, 0.5085, 0.4709, 0.2581, 0.9289, 220 | 0.0975, 0.0357, 0.3171, 0.1626, 0.2575, 0.2858, 0.7943, 0.9961, 0.2638, 0.2400, 0.1320, 0.2963, 0.5108, 0.2305, 0.4087, 0.7303, 221 | 0.2785, 0.8491, 0.9502, 0.1190, 0.8407, 0.7572, 0.3112, 0.0782, 0.1455, 0.4173, 0.9421, 0.7447, 0.8176, 0.8443, 0.5949, 0.4886, 222 | 0.5469, 0.9340, 0.0344, 0.4984, 0.2543, 0.7537, 0.5285, 0.4427, 0.1361, 0.0497, 0.9561, 0.1890, 0.7948, 0.1948, 0.2622, 0.5785, 223 | 0.9575, 0.6787, 0.4387, 0.9597, 0.8143, 0.3804, 0.1656, 0.1067, 0.8693, 0.9027, 0.5752, 0.6868, 0.6443, 0.2259, 0.6028, 0.2373, 224 | 0.9649, 0.7577, 0.3816, 0.3404, 0.2435, 0.5678, 0.6020, 0.9619, 0.5797, 0.9448, 0.0598, 0.1835, 0.3786, 0.1707, 0.7112, 0.4588, 225 | 0.1576, 0.7431, 0.7655, 0.5853, 0.9293, 0.0759, 0.2630, 0.0046, 0.5499, 0.4909, 0.2348, 0.3685, 0.8116, 0.2277, 0.2217, 0.9631, 226 | 0.9706, 0.3922, 0.7952, 0.2238, 0.3500, 0.0540, 0.6541, 0.7749, 0.1450, 0.4893, 0.3532, 0.6256, 0.5328, 0.4357, 0.1174, 0.5468, 227 | 0.9572, 0.6555, 0.1869, 0.7513, 0.1966, 0.5308, 0.6892, 0.8173, 0.8530, 0.3377, 0.8212, 0.7802, 0.3507, 0.3111, 0.2967, 0.5211, 228 | 0.4854, 0.1712, 0.4898, 0.2551, 0.2511, 0.7792, 0.7482, 0.8687, 0.6221, 0.9001, 0.0154, 0.0811, 0.9390, 0.9234, 0.3188, 0.2316, 229 | 0.8003, 0.7060, 0.4456, 0.5060, 0.6160, 0.9340, 0.4505, 0.0844, 0.3510, 0.3692, 0.0430, 0.9294, 0.8759, 0.4302, 0.4242, 0.4889, 230 | 0.1419, 0.0318, 0.6463, 0.6991, 0.4733, 0.1299, 0.0838, 0.3998, 0.5132, 0.1112, 0.1690, 0.7757, 0.5502, 0.1848, 0.5079, 0.6241 }, 16, 16); 231 | std::cout << "big_mat :\n" << big_mat << "\n"; 232 | std::cout << "big_mat^-1 :\n" << matrix_f64::invert(big_mat) << "\n"; 233 | std::cout << "big_mat * big_mat^-1:\n" << big_mat / big_mat << "\n"; 234 | 235 | std::cout << "rhs + col:\n" << rhs.add_row({ 1, 2, 3 }) << "\n"; 236 | std::cout << "rhs + col:\n" << rhs.add_col({ 100, 100, 100, 100 }) << "\n"; 237 | auto row = rhs.get_row(0); 238 | // rhs.get_row(0) -= row; 239 | // std::cout << "rhs - rhs[0:]:\n" << rhs<< "\n"; 240 | rhs.get_row(1) -= row; 241 | std::cout << "rhs - rhs[1:]:\n" << rhs << "\n"; 242 | rhs.get_row(2) -= row; 243 | std::cout << "rhs - rhs[2:]:\n" << rhs << "\n"; 244 | rhs.get_row(3) -= row; 245 | std::cout << "rhs - rhs[3:]:\n" << rhs << "\n"; 246 | } 247 | NUMERICS_NAMESPACE_END -------------------------------------------------------------------------------- /C++/OptimizationMethods/numerics/linalg/numeric_matrix.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuryStrelkov/OptimizationMethods/745af24e1c78df1e600e5f87423bf7f3d3ceaf8b/C++/OptimizationMethods/numerics/linalg/numeric_matrix.h -------------------------------------------------------------------------------- /C++/OptimizationMethods/numerics/linalg/slice.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __SLICE_H__ 3 | #define __SLICE_H__ 4 | #include "../common.h" 5 | NUMERICS_NAMESPACE_BEGIN 6 | struct slice 7 | { 8 | private: 9 | I32 m_end; 10 | I32 m_begin; 11 | I32 m_step; 12 | //exclusive index 13 | public: 14 | I32 end()const { 15 | return m_end; 16 | } 17 | //inclusive index 18 | I32 begin()const { 19 | return m_begin; 20 | } 21 | 22 | I32 step()const { 23 | return m_step; 24 | } 25 | 26 | slice() : slice(0, 0, 1) { 27 | } 28 | 29 | slice(const I32 begin, const I32 end) : slice(begin, end, 1) { 30 | } 31 | 32 | slice(const I32 begin, const I32 end, const I32 step) { 33 | m_step = step; 34 | m_begin = begin; 35 | m_end = end; 36 | } 37 | 38 | friend std::ostream& operator<<(std::ostream& stream, const slice& slice); 39 | }; 40 | NUMERICS_NAMESPACE_END 41 | #endif -------------------------------------------------------------------------------- /C++/OptimizationMethods/numerics/linalg/template_vector_allocator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __TEMPLATE_VECTOR_ALLOCATOR__ 3 | #define __TEMPLATE_VECTOR_ALLOCATOR__ 4 | #include "..\common.h" 5 | 6 | template struct template_vector_allocator 7 | { 8 | private: 9 | UI8 validate(const T* src, const T* dst)const 10 | { 11 | return src && dst; 12 | } 13 | public: 14 | template_vector_allocator() = default; 15 | ~template_vector_allocator() = default; 16 | T* zero_mem(T* block, const UI64 amount = 0)const noexcept 17 | { 18 | STR mem_block = reinterpret_cast (block); 19 | if (amount) 20 | for (UI32 index = 0; index < amount * sizeof(T); index++) *(mem_block++) = '\0'; 21 | else 22 | for (UI32 index = 0; index < sizeof(T); index++) *(mem_block++) = '\0'; 23 | return block; 24 | } 25 | T* allocate(const size_t amount)const noexcept 26 | { 27 | return (T*)malloc(sizeof(T) * amount); 28 | } 29 | UI8 deallocate(T** block, const size_t amount)const noexcept 30 | { 31 | if(!amount) return FALSE; 32 | if (!*block) return FALSE; 33 | T* start = *block; 34 | T* end = *block + amount; 35 | while (start != end) 36 | { 37 | start->~T(); 38 | start++; 39 | } 40 | free(*block); 41 | *block = nullptr; 42 | return TRUE; 43 | } 44 | void move_copy(T* src, T* dst, const size_t amount)const noexcept 45 | { 46 | if (!validate(src, dst))return; 47 | for (size_t index = 0; index < amount; index++, src++, dst++) *zero_mem(dst) = std::move(*src); 48 | } 49 | void const_copy(const T* src, T* dst, const size_t amount)const noexcept 50 | { 51 | if (!validate(src, dst))return; 52 | for (size_t index = 0; index < amount; index++, src++, dst++) *dst = T(*src); 53 | } 54 | void move_copy_reverced(T* src, T* dst, const size_t amount)const noexcept 55 | { 56 | if (!validate(src, dst))return; 57 | for (size_t index = 0; index < amount; index++, src--, dst--) *zero_mem(dst) = std::move(*src); 58 | } 59 | void const_copy_reverced(const T* src, T* dst, const size_t amount)const noexcept 60 | { 61 | if (!validate(src, dst))return; 62 | for (size_t index = 0; index < amount; index++, src--, dst--) *dst = T(*src); 63 | } 64 | }; 65 | #endif -------------------------------------------------------------------------------- /C++/OptimizationMethods/numerics/linalg/vector_iterators.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __TEMPLATE_ITERATOR_H__ 3 | #define __TEMPLATE_ITERATOR_H__ 4 | #include "../common.h" 5 | NUMERICS_NAMESPACE_BEGIN 6 | /// template 7 | /// struct iterator_ : public std::iterator< 8 | /// std::input_iterator_tag, // iterator_category 9 | /// Type, // value_type 10 | /// Type, // difference_type 11 | /// const Type*, // pointer 12 | /// const Type&> // reference 13 | /// { 14 | /// // public: 15 | /// // bool operator!=(const iterator_& other) const { return !(*this == other); } 16 | /// // bool operator==(const iterator_& other) const { return false; } 17 | /// // iterator_ operator++(int) { iterator_ retval = *this; ++(*this); return retval; } 18 | /// // iterator_& operator++() { return *this; } 19 | /// // const Type* operator* () const { return nullptr; } 20 | /// // const Type& operator& () const { return 0; } 21 | /// }; 22 | 23 | template struct iterable_ 24 | { 25 | public: 26 | virtual T begin()const = 0; 27 | virtual T end() const = 0; 28 | }; 29 | 30 | ////////////////////////////////////// 31 | /// Iterator over indices range /// 32 | ////////////////////////////////////// 33 | class indices_iterator // : public iterator_ 34 | { 35 | private: 36 | I32 m_index; 37 | I32 m_step; 38 | public: 39 | indices_iterator(const I32 index, const I32 step) 40 | { 41 | m_index = index; 42 | m_step = step; 43 | } 44 | bool operator==(const indices_iterator& other) const { return m_index == other.m_index; } 45 | bool operator!=(const indices_iterator& other) const { return !(*this == other); } 46 | indices_iterator& operator++() { m_index += m_step; return *this; } 47 | indices_iterator operator++(int) { indices_iterator& retval = *this; ++(*this); return retval; } 48 | I32 operator*() const { return m_index; } 49 | const I32* operator&() const { return &m_index; } 50 | }; 51 | 52 | struct vector_indices : iterable_ 53 | { 54 | private: 55 | const I32 m_begin; 56 | const I32 m_end; 57 | const I32 m_step; 58 | public: 59 | vector_indices(const I32 start, const I32 stop, const I32 step) :m_begin(start), m_end(stop), m_step(step) {} 60 | vector_indices(const I32 start, const I32 stop) :m_begin(start), m_end(stop), m_step(1) {} 61 | vector_indices(const I32 range) :m_begin(0), m_end(range), m_step(1) {} 62 | indices_iterator begin() const override { return indices_iterator(m_begin, m_step); } 63 | indices_iterator end() const override { return indices_iterator(m_end, m_step); } 64 | }; 65 | 66 | ////////////////////////////////////// 67 | /// Iterator over vector values /// 68 | ////////////////////////////////////// 69 | template 70 | struct values_iterator // : public iterator_ 71 | { 72 | private: 73 | const T* m_data; 74 | indices_iterator m_index; 75 | public: 76 | values_iterator(const T* data, indices_iterator&& indices) : m_data(data), m_index(std::move(indices)) {} 77 | values_iterator(const T value) : m_data(&value), m_index(vector_indices(0, 0, 0)) {} 78 | bool operator==(const values_iterator& other) const { return m_index == other.m_index; } 79 | bool operator!=(const values_iterator& other) const { return !(*this == other); } 80 | values_iterator& operator++() { m_index++; return *this; } 81 | values_iterator operator++(int) { values_iterator retval = *this; ++(*this); return retval; } 82 | const T& operator* ()const { return m_data[*m_index]; } 83 | const T* operator& ()const { return m_data[*m_index]; } 84 | // T& operator* (){ return m_data[*m_index]; } 85 | // T* operator& (){ return m_data[*m_index]; } 86 | }; 87 | 88 | template 89 | struct vector_values : public iterable_> 90 | { 91 | private: 92 | const T* m_data; 93 | const vector_indices m_indices; 94 | public: 95 | vector_values(const T* data, vector_indices&& indices) : m_data(data), m_indices(indices) {} 96 | vector_values(const T& value) : m_data(&value), m_indices(vector_indices(0, 1, 0)) {} 97 | values_iterator begin() const override { return values_iterator(m_data, m_indices.begin()); } 98 | values_iterator end() const override { return values_iterator(m_data, m_indices.end()); } 99 | }; 100 | 101 | ///////////////////////////////////////////// 102 | /// Iterator over mapped vector values /// 103 | ///////////////////////////////////////////// 104 | template 105 | struct map_values_iterator // : public iterator_ 106 | { 107 | private: 108 | values_iterator m_values; 109 | const std::function m_map_function; 110 | public: 111 | map_values_iterator(values_iterator&& values, std::function map_function) : m_map_function(map_function), m_values(values) {} 112 | bool operator==(const map_values_iterator& other) const { return m_values == other.m_values; } 113 | bool operator!=(const map_values_iterator& other) const { return !(*this == other); } 114 | map_values_iterator& operator++() { m_values++; return *this; } 115 | map_values_iterator operator++(int) { map_values_iterator retval = *this; ++(*this); return retval; } 116 | const T2 operator* () const { return m_map_function(*m_values); } 117 | const T2 operator& () const { return m_map_function(*m_values); } 118 | 119 | // const T2& operator* () const {return m_map_function(*m_values);} 120 | // const T2* operator& () const {return m_map_function(*m_values);} 121 | }; 122 | 123 | template 124 | struct map_values : public iterable_> 125 | { 126 | private: 127 | const std::function m_map_function; 128 | const vector_values m_values; 129 | public: 130 | map_values(vector_values&& values, std::function map_function) : m_values(values), m_map_function(map_function) {} 131 | map_values_iterator begin() const override { return map_values_iterator(m_values.begin(), m_map_function); } 132 | map_values_iterator end() const override { return map_values_iterator(m_values.end(), m_map_function); } 133 | }; 134 | 135 | 136 | /////////////////////////////////////////////// 137 | /// Iterator over values of vectors pair /// 138 | /////////////////////////////////////////////// 139 | template 140 | struct pair_ 141 | { 142 | public: 143 | const T1& first; 144 | const T2& second; 145 | pair_(const T1& first, const T2& second) : first(first), second(second) {} 146 | template 147 | friend std::ostream& operator<<(std::ostream& steram, const pair_& pair); 148 | }; 149 | 150 | template 151 | inline std::ostream& operator<<(std::ostream& steram, const pair_& pair) 152 | { 153 | // TODO: âñòàâüòå çäåñü îïåðàòîð return 154 | steram << "{ \"first\" : " << pair.first << ", \"second\": " << pair.second << " }"; 155 | return steram; 156 | } 157 | 158 | template 159 | struct zip_values_iterator /// : public iterator_> 160 | { 161 | private: 162 | values_iterator m_iterable1; 163 | values_iterator m_iterable2; 164 | public: 165 | zip_values_iterator(values_iterator&& values1, values_iterator&& values2) : m_iterable1(values1), m_iterable2(values2) {} 166 | bool operator==(const zip_values_iterator& other) const { return (m_iterable1 == other.m_iterable1) || (m_iterable2 == other.m_iterable2); } 167 | bool operator!=(const zip_values_iterator& other) const { return !(*this == other); } 168 | zip_values_iterator& operator++() { m_iterable1++; m_iterable2++; return *this; } 169 | zip_values_iterator operator++(int) { zip_values_iterator retval = *this; ++(*this); return retval; } 170 | const pair_ operator*() const { return pair_(*m_iterable1, *m_iterable2); } 171 | const pair_ operator&() const { return pair_(*m_iterable1, *m_iterable2); } 172 | }; 173 | 174 | template 175 | struct zip_values : public iterable_> 176 | { 177 | private: 178 | const vector_valuesm_values1; 179 | const vector_valuesm_values2; 180 | public: 181 | zip_values(vector_values&& values1, vector_values&& values2) : m_values1(values1), m_values2(values2) {} 182 | zip_values(const T1& value, vector_values&& values2) : m_values1(vector_values(value)), m_values2(values2) {} 183 | zip_values(vector_values&& values1, const T2& value) : m_values1(values1), m_values2(vector_values(value)) {} 184 | zip_values_iterator begin() const override { return zip_values_iterator(m_values1.begin(), m_values2.begin()); } 185 | zip_values_iterator end() const override { return zip_values_iterator(m_values1.end(), m_values2.end()); } 186 | }; 187 | 188 | /////////////////////////////////////////////// 189 | /// Combine iterator /// 190 | /////////////////////////////////////////////// 191 | 192 | template 193 | struct combine_values_iterator// : public iterator_ 194 | { 195 | private: 196 | zip_values_iterator m_iterables; 197 | const std::function m_combine_function; 198 | public: 199 | combine_values_iterator(zip_values_iterator&& zip_values, 200 | std::function combine_f) : m_iterables(zip_values), m_combine_function(combine_f) {} 201 | bool operator==(const combine_values_iterator& other) const { return m_iterables == other.m_iterables; } 202 | bool operator!=(const combine_values_iterator& other) const { return !(*this == other); } 203 | combine_values_iterator& operator++() { m_iterables++; return *this; } 204 | combine_values_iterator operator++(int) { combine_values_iterator retval = *this; ++(*this); return retval; } 205 | const T2 operator*() const { return m_combine_function((*m_iterables).first, (*m_iterables).second); } 206 | const T2 operator&() const { return m_combine_function((*m_iterables).first, (*m_iterables).second); } 207 | }; 208 | 209 | template 210 | struct combine_values : public iterable_> 211 | { 212 | private: 213 | const zip_values m_iterables; 214 | const std::function m_combine_function; 215 | public: 216 | combine_values(zip_values&& zip_vals, std::function combine_f) : 217 | m_iterables(zip_vals), m_combine_function(combine_f) { 218 | } 219 | 220 | combine_values(vector_values&& values1, 221 | vector_values&& values2, 222 | std::function combine_f) : 223 | m_iterables(zip_values(std::move(values1), std::move(values2))), m_combine_function(combine_f) { 224 | } 225 | combine_values(const T1& value, vector_values&& values2, std::function combine_f) : m_iterables(zip_values(value, std::move(values2))), m_combine_function(combine_f) {} 226 | combine_values(vector_values&& values1, const T1& value, std::function combine_f) : m_iterables(zip_values(std::move(values1), value)), m_combine_function(combine_f) {} 227 | combine_values_iterator begin() const override { return combine_values_iterator(m_iterables.begin(), m_combine_function); } 228 | combine_values_iterator end() const override { return combine_values_iterator(m_iterables.end(), m_combine_function); } 229 | }; 230 | NUMERICS_NAMESPACE_END 231 | #endif -------------------------------------------------------------------------------- /C++/OptimizationMethods/numerics/numeric_utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "linalg/numeric_vector.h" 3 | 4 | static int get_factorial(const I32 number) { 5 | int result = 1; 6 | for (int i = 1; i <= number; i++) result = result * i; 7 | return result; 8 | }; 9 | 10 | static numerics::vector_i32 calculate_factorials(const I32 number = 128) 11 | { 12 | numerics::vector_i32 factorials(number); 13 | factorials.fill([](const I32 index) {return get_factorial(index); }); 14 | return factorials; 15 | }; 16 | 17 | static numerics::vector_i32 fibonacci_numbers(const I32 index) { 18 | if (index < 1) return numerics::vector_i32({ 0 }); 19 | if (index < 2) return numerics::vector_i32({ 0, 1 }); 20 | numerics::vector_i32 res = numerics::vector_i32(index); 21 | res[0] = 0; 22 | res[1] = 1; 23 | for (int i = 2; i < index; i++) res[i] = res[i - 1] + res[i - 2]; 24 | return res; 25 | }; 26 | 27 | static void closest_fibonacci_pair(const F64 value, I32& fib_n, I32& fib_n_1) { 28 | fib_n = 0; 29 | fib_n_1 = 0; 30 | if (value < 1) return; 31 | fib_n_1 = 1; 32 | if (value < 2) return; 33 | int f_tmp; 34 | while (fib_n < value) { 35 | f_tmp = fib_n; 36 | fib_n = fib_n_1; 37 | fib_n_1 += f_tmp; 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /C++/OptimizationMethods/numerics/numerics.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __NUMERICS_H__ 3 | #define __NUMERICS_H__ 4 | #include "linalg/numeric_matrix.h" 5 | #include "linalg/numeric_vector.h" 6 | #include "rational/rational.h" 7 | #endif -------------------------------------------------------------------------------- /C++/OptimizationMethods/numerics/rational/rational.cpp: -------------------------------------------------------------------------------- 1 | #include "rational.h" 2 | NUMERICS_NAMESPACE_BEGIN 3 | std::ostream& operator<<(std::ostream& stream, const rational_number& number) 4 | { 5 | return stream << rational_str(number.int_part(), number.numerator(), number.denominator(), false); 6 | } 7 | NUMERICS_NAMESPACE_END -------------------------------------------------------------------------------- /C++/OptimizationMethods/numerics/rational/rational.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuryStrelkov/OptimizationMethods/745af24e1c78df1e600e5f87423bf7f3d3ceaf8b/C++/OptimizationMethods/numerics/rational/rational.h -------------------------------------------------------------------------------- /C++/OptimizationMethods/one_dimensional.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "numerics/common.h" 3 | 4 | typedef F64(*function_1d)(const F64); 5 | static F64 bisect (function_1d function, F64 left, F64 right, const F64 eps = ACCURACY, const I32 max_iterations = ITERS_MAX); 6 | static F64 golden_ratio(function_1d function, F64 left, F64 right, const F64 eps = ACCURACY, const I32 max_iterations = ITERS_MAX); 7 | static F64 fibonacci (function_1d function, F64 left, F64 right, const F64 eps = ACCURACY); 8 | 9 | static F64 bisect(function_1d function, F64 left, F64 right, const F64 eps, const I32 max_iterations) 10 | { 11 | if (left > right) std::swap(left, right); 12 | F64 x_c = 0.0; 13 | I32 iteration = 0; 14 | for (; iteration != max_iterations && abs(right - left) > 2 * eps; iteration++) 15 | { 16 | x_c = (right + left) * 0.5; 17 | if (function(x_c - eps * 1e-1) > function(x_c + eps * 1e-1)) 18 | left = x_c; 19 | else 20 | right = x_c; 21 | } 22 | #if _DEBUG 23 | std::cout << "bisect::function arg range : " << right - left << "\n"; 24 | std::cout << "bisect::function probes count : " << iteration * 2 << "\n"; 25 | #endif 26 | return (right + left) * 0.5; 27 | } 28 | 29 | static F64 golden_ratio(function_1d function, F64 left, F64 right, const F64 eps, const I32 max_iterations) 30 | { 31 | if (left > right) std::swap(left, right); 32 | I32 iteration = 0; 33 | F64 x_l = right - (right - left) * PSI; 34 | F64 x_r = left + (right - left) * PSI; 35 | F64 f_l = function(x_l); 36 | F64 f_r = function(x_r); 37 | for (; iteration != max_iterations && abs(right - left) > 2 * eps; iteration++) 38 | { 39 | if (f_l > f_r) 40 | { 41 | left = x_l; 42 | x_l = x_r; 43 | f_l = f_r; 44 | x_r = left + (right - left) * PSI; 45 | f_r = function(x_r); 46 | } 47 | else 48 | { 49 | right = x_r; 50 | x_r = x_l; 51 | f_r = f_l; 52 | x_l = right - (right - left) * PSI; 53 | f_l = function(x_l); 54 | } 55 | } 56 | #if _DEBUG 57 | std::cout << "golden_ratio::function arg range : " << right - left << "\n"; 58 | std::cout << "golden_ratio::function probes count : " << iteration + 2 << "\n"; 59 | #endif 60 | return (right + left) * 0.5; 61 | } 62 | 63 | static F64 fibonacci(function_1d function, F64 left, F64 right, const F64 eps) 64 | { 65 | if (left > right) std::swap(left, right); 66 | F64 condition = (right - left) / eps; 67 | F64 fib_t{ 0.0 }, fib_1{ 1.0 }, fib_2{ 1.0 }; 68 | I32 iterations{ 0 }; 69 | while (fib_2 < condition) 70 | { 71 | iterations++; 72 | fib_t = fib_1; 73 | fib_1 = fib_2; 74 | fib_2 += fib_t; 75 | } 76 | F64 x_l = left + (right - left) * ((fib_2 - fib_1) / fib_2); 77 | F64 x_r = left + (right - left) * ( fib_1 / fib_2); 78 | 79 | F64 f_l = function(x_l); 80 | F64 f_r = function(x_r); 81 | 82 | for(I32 index = iterations; index; index--) 83 | { 84 | fib_t = fib_2 - fib_1; 85 | fib_2 = fib_1; 86 | fib_1 = fib_t; 87 | if (f_l > f_r) 88 | { 89 | left = x_l; 90 | f_l = f_r; 91 | x_l = x_r; 92 | x_r = left + (right - left) * (fib_1 / fib_2); 93 | f_r = function(x_r); 94 | } 95 | else 96 | { 97 | right = x_r; 98 | x_r = x_l; 99 | f_r = f_l; 100 | x_l = left + (right - left) * ((fib_2 - fib_1) / fib_2); 101 | f_l = function(x_l); 102 | } 103 | #if _DEBUG 104 | std::cout << "\nfibonacchi [a, b] range: " << (right - left) << "\n"; 105 | #endif 106 | } 107 | #if _DEBUG 108 | std::cout << "fibonacci::function arg range : " << right - left << "\n"; 109 | std::cout << "fibonacci::function probes count : " << iterations + 2 << "\n"; 110 | #endif 111 | return (right + left) * 0.5; 112 | } 113 | -------------------------------------------------------------------------------- /C++/OptimizationMethods/simplex.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuryStrelkov/OptimizationMethods/745af24e1c78df1e600e5f87423bf7f3d3ceaf8b/C++/OptimizationMethods/simplex.h -------------------------------------------------------------------------------- /C++/OptimizationMethods/test.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuryStrelkov/OptimizationMethods/745af24e1c78df1e600e5f87423bf7f3d3ceaf8b/C++/OptimizationMethods/test.h -------------------------------------------------------------------------------- /Java/OptimizationMethods/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | 8 | ### IntelliJ IDEA ### 9 | .idea 10 | *.iws 11 | *.iml 12 | *.ipr 13 | 14 | !**/src/main/**/build/ 15 | !**/src/test/**/build/ 16 | -------------------------------------------------------------------------------- /Java/OptimizationMethods/OptimizationMethods.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Java/OptimizationMethods/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | groupId 8 | OptimizationMethods 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 13 | org.apache.maven.plugins 14 | maven-compiler-plugin 15 | 16 | 17 17 | 17 18 | 19 | 20 | 21 | 22 | 23 | 24 | 18 25 | 18 26 | 27 | 28 | -------------------------------------------------------------------------------- /Java/OptimizationMethods/src/main/java/Main.java: -------------------------------------------------------------------------------- 1 | import mathUtils.*; 2 | 3 | public class Main { 4 | public static void main(String[] args) 5 | { 6 | TemplateVector vector = new TemplateVector<>(1.0f, 2.0f, 3.0f, 4.0f, 5.0f); 7 | System.out.println(vector); 8 | System.out.println(vector.insert(0, 111.0f)); 9 | System.out.println(vector.insert(3, 333.0f)); 10 | System.out.println(vector.insert(vector.size(), 999.0f)); 11 | System.out.println(vector.pushBack(1.333f)); 12 | System.out.println(vector.pushBack(1.333f)); 13 | System.out.println(vector.pushBack(1.333f)); 14 | System.out.println(vector.pushBack(1.333f)); 15 | System.out.println(vector.pushBack(1.333f)); 16 | System.out.println(vector.pushBack(1.333f)); 17 | System.out.println(vector.pushBack(1.333f)); 18 | System.out.println(vector.pushBack(1.333f)); 19 | System.out.println(vector.pushBack(1.333f)); 20 | System.out.println(vector.pushBack(9.999f)); 21 | System.out.println(vector.removeAt(0)); 22 | System.out.println(vector.removeAt(2)); 23 | System.out.println(vector.removeAt(vector.size() - 1)); 24 | System.out.println(new TemplateVector<>(vector)); 25 | System.out.println(vector.get(new Slice(0, -1, 2))); 26 | 27 | // Tests.numericTests(); //Pass 28 | Tests.VectorTest(); //Pass 29 | Tests.matrixTest(); //Pass 30 | // Tests.oneDimensionalMethodsTest(); //Pass 31 | // Tests.multiDimensionalMethodsTest(); //Pass 32 | // Tests.simplexTest(); //Pass 33 | // TemplateVector signs_equal = new TemplateVector<>(Sign.More, Sign.Less, Sign.Less); 34 | // Simplex sym_0 = new Simplex( 35 | // /*A*/new DoubleMatrix(new DoubleVector( 1.0, 1.0), 36 | // new DoubleVector( 2.0, -1.0), 37 | // new DoubleVector( 1.0, 4.0)), 38 | // /*c*/new DoubleVector( -1.0, 1.0), 39 | // /*inequalities*/signs_equal, 40 | // /*b*/new DoubleVector( 5.0, 7.0, 17.0)); 41 | // NumericCommon.SHOW_SIMPLEX_DEBUG_LOG = true; 42 | // sym_0.solve(SimplexProblemType.Max); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Java/OptimizationMethods/src/main/java/MultiDimensional.java: -------------------------------------------------------------------------------- 1 | import mathUtils.functionalInterfaces.IFunctionND; 2 | import mathUtils.NumericCommon; 3 | import mathUtils.DoubleVector; 4 | import mathUtils.DoubleMatrix; 5 | import java.util.Objects; 6 | 7 | @SuppressWarnings("all") 8 | public class MultiDimensional { 9 | //////////////////// 10 | /// Lab. work #2 /// 11 | //////////////////// 12 | public static DoubleVector biSect(IFunctionND function, DoubleVector left, DoubleVector right, 13 | double eps, int maxIterations) { 14 | DoubleVector lhs = new DoubleVector(left); 15 | DoubleVector rhs = new DoubleVector(right); 16 | DoubleVector x_c, dir = DoubleVector.direction(lhs, rhs).mul(eps); 17 | int iteration = 0; 18 | for (; iteration != maxIterations && DoubleVector.distance(rhs, lhs) > 2 * eps; iteration++) { 19 | x_c = DoubleVector.add(rhs, lhs).mul(0.5); 20 | if (function.call(DoubleVector.add(x_c, dir)) > function.call(DoubleVector.sub(x_c, dir))) 21 | rhs = x_c; 22 | else 23 | lhs = x_c; 24 | } 25 | if (NumericCommon.SHOW_ZERO_ORDER_METHODS_DEBUG_LOG) { 26 | System.out.printf("biSect::function arg range : %s\n", DoubleVector.distance(rhs, lhs)); 27 | System.out.printf("biSect::function probes count : %s\n", 2 * iteration); 28 | } 29 | return DoubleVector.add(rhs, lhs).mul(0.5); 30 | } 31 | 32 | public static DoubleVector biSect(IFunctionND function, DoubleVector left, DoubleVector right, double eps) { 33 | return biSect(function, left, right, eps, NumericCommon.ITERATIONS_COUNT_HIGH); 34 | } 35 | 36 | public static DoubleVector biSect(IFunctionND function, DoubleVector left, DoubleVector right) { 37 | return biSect(function, left, right, NumericCommon.NUMERIC_ACCURACY_MIDDLE, NumericCommon.ITERATIONS_COUNT_HIGH); 38 | } 39 | 40 | public static DoubleVector goldenRatio(IFunctionND function, DoubleVector left, DoubleVector right, 41 | double eps, int maxIterations) { 42 | DoubleVector lhs = new DoubleVector(left); 43 | DoubleVector rhs = new DoubleVector(right); 44 | DoubleVector x_l = DoubleVector.sub(rhs, DoubleVector.mul(DoubleVector.sub(rhs, lhs), NumericCommon.PSI)); 45 | DoubleVector x_r = DoubleVector.add(lhs, DoubleVector.mul(DoubleVector.sub(rhs, lhs), NumericCommon.PSI)); 46 | double f_l = function.call(x_l); 47 | double f_r = function.call(x_r); 48 | int iteration = 0; 49 | for (; iteration != maxIterations && DoubleVector.distance(rhs, lhs) > 2 * eps; iteration++) { 50 | if (f_l > f_r) { 51 | lhs = x_l; 52 | x_l = x_r; 53 | f_l = f_r; 54 | x_r = DoubleVector.add(lhs, DoubleVector.mul(DoubleVector.sub(rhs, lhs), NumericCommon.PSI)); 55 | f_r = function.call(x_r); 56 | } else { 57 | rhs = x_r; 58 | x_r = x_l; 59 | f_r = f_l; 60 | x_l = DoubleVector.sub(rhs, DoubleVector.mul(DoubleVector.sub(rhs, lhs), NumericCommon.PSI)); 61 | f_l = function.call(x_l); 62 | } 63 | } 64 | if (NumericCommon.SHOW_ZERO_ORDER_METHODS_DEBUG_LOG) { 65 | System.out.printf("goldenRatio::function arg range : %s\n", DoubleVector.distance(rhs, lhs)); 66 | System.out.printf("goldenRatio::function probes count : %s\n", 2 + iteration); 67 | } 68 | return DoubleVector.add(rhs, lhs).mul(0.5); 69 | } 70 | 71 | public static DoubleVector goldenRatio(IFunctionND function, DoubleVector left, DoubleVector right, double eps) { 72 | return goldenRatio(function, left, right, eps, NumericCommon.ITERATIONS_COUNT_HIGH); 73 | } 74 | 75 | public static DoubleVector goldenRatio(IFunctionND f, DoubleVector left, DoubleVector right) { 76 | return goldenRatio(f, left, right, NumericCommon.NUMERIC_ACCURACY_MIDDLE, NumericCommon.ITERATIONS_COUNT_HIGH); 77 | } 78 | 79 | public static DoubleVector fibonacci(IFunctionND function, DoubleVector left, DoubleVector right, double eps) { 80 | DoubleVector lhs = new DoubleVector(left); 81 | DoubleVector rhs = new DoubleVector(right); 82 | double condition, fib_t, fib_1 = 1.0, fib_2 = 1.0; 83 | int iterations = 0; 84 | condition = DoubleVector.distance(rhs, lhs) / eps; 85 | while (fib_2 < condition) { 86 | iterations++; 87 | fib_t = fib_1; 88 | fib_1 = fib_2; 89 | fib_2 += fib_t; 90 | } 91 | DoubleVector x_l = DoubleVector.add(lhs, DoubleVector.mul(DoubleVector.sub(rhs, lhs), (fib_2 - fib_1) / fib_2)); 92 | DoubleVector x_r = DoubleVector.add(lhs, DoubleVector.mul(DoubleVector.sub(rhs, lhs), fib_1 / fib_2)); 93 | double f_l = function.call(x_l); 94 | double f_r = function.call(x_r); 95 | for (int index = iterations; index > 0; index--) { 96 | fib_t = fib_2 - fib_1; 97 | fib_2 = fib_1; 98 | fib_1 = fib_t; 99 | if (f_l > f_r) { 100 | lhs = x_l; 101 | x_l = x_r; 102 | f_l = f_r; 103 | x_r = DoubleVector.add(lhs, DoubleVector.mul(DoubleVector.sub(rhs, lhs), fib_1 / fib_2)); 104 | f_r = function.call(x_r); 105 | } else { 106 | rhs = x_r; 107 | x_r = x_l; 108 | f_r = f_l; 109 | x_l = DoubleVector.add(lhs, DoubleVector.mul(DoubleVector.sub(rhs, lhs), (fib_2 - fib_1) / fib_2)); 110 | f_l = function.call(x_l); 111 | } 112 | } 113 | if (NumericCommon.SHOW_ZERO_ORDER_METHODS_DEBUG_LOG) { 114 | System.out.printf("goldenRatio::function arg range : %s\n", DoubleVector.distance(rhs, lhs)); 115 | System.out.printf("goldenRatio::function probes count : %s\n", 2 + iterations); 116 | } 117 | return DoubleVector.add(rhs, lhs).mul(0.5); 118 | } 119 | 120 | public static DoubleVector fibonacci(IFunctionND function, DoubleVector left, DoubleVector right) { 121 | return fibonacci(function, left, right, NumericCommon.NUMERIC_ACCURACY_MIDDLE); 122 | } 123 | 124 | public static DoubleVector perCordDescend(IFunctionND function, DoubleVector xStart, double eps, int maxIterations) { 125 | DoubleVector x_0 = new DoubleVector(xStart); 126 | DoubleVector x_1 = new DoubleVector(xStart); 127 | double step = 1.0; 128 | double x_i, y_1, y_0; 129 | int optCoordinatesCount = 0, coordinateId; 130 | for (int iteration = 0; iteration < maxIterations; iteration++) { 131 | coordinateId = iteration % x_0.size(); 132 | x_1.set(coordinateId, x_1.get(coordinateId) - eps); 133 | y_0 = function.call(x_1); 134 | x_1.set(coordinateId, x_1.get(coordinateId) + 2 * eps); 135 | y_1 = function.call(x_1); 136 | x_1.set(coordinateId, x_1.get(coordinateId) - eps); 137 | x_1.set(coordinateId, y_0 > y_1 ? x_1.get(coordinateId) + step : x_1.get(coordinateId) - step); 138 | x_i = x_0.get(coordinateId); 139 | x_1 = biSect(function, x_0, x_1, eps, maxIterations); 140 | x_0 = new DoubleVector(x_1); 141 | if (Math.abs(x_1.get(coordinateId) - x_i) < 2 * eps) { 142 | optCoordinatesCount++; 143 | if (optCoordinatesCount == x_1.size()) { 144 | if (NumericCommon.SHOW_DEBUG_LOG) 145 | System.out.printf("per cord descend iterations number : %s\n", iteration + 1); 146 | return x_0; 147 | } 148 | continue; 149 | } 150 | optCoordinatesCount = 0; 151 | } 152 | if (NumericCommon.SHOW_DEBUG_LOG) System.out.printf("per cord descend iterations number : %s\n", maxIterations); 153 | return x_0; 154 | } 155 | 156 | public static DoubleVector perCordDescend(IFunctionND function, DoubleVector xStart, double eps) { 157 | return perCordDescend(function, xStart, eps, NumericCommon.ITERATIONS_COUNT_HIGH); 158 | } 159 | 160 | public static DoubleVector perCordDescend(IFunctionND function, DoubleVector xStart) { 161 | return perCordDescend(function, xStart, NumericCommon.NUMERIC_ACCURACY_MIDDLE, NumericCommon.ITERATIONS_COUNT_HIGH); 162 | } 163 | 164 | //////////////////// 165 | /// Lab. work #3 /// 166 | //////////////////// 167 | public static DoubleVector gradientDescend(IFunctionND function, DoubleVector xStart, double eps, int maxIterations) { 168 | DoubleVector x_i = new DoubleVector(xStart); 169 | DoubleVector x_i_1 = new DoubleVector(xStart); 170 | int cntr = 0; 171 | for (; cntr != maxIterations; cntr++) { 172 | x_i_1 = DoubleVector.sub(x_i, DoubleVector.gradient(function, x_i, eps)); 173 | x_i_1 = biSect(function, x_i, x_i_1, eps, maxIterations); 174 | if (DoubleVector.distance(x_i_1, x_i) < 2 * eps) break; 175 | x_i = x_i_1; 176 | } 177 | 178 | if (NumericCommon.SHOW_DEBUG_LOG) System.out.printf("gradient descend iterations number : %s\n", cntr + 1); 179 | 180 | return DoubleVector.add(x_i_1, x_i).mul(0.5); 181 | } 182 | 183 | public static DoubleVector gradientDescend(IFunctionND function, DoubleVector xStart, double eps) { 184 | return gradientDescend(function, xStart, eps, NumericCommon.ITERATIONS_COUNT_HIGH); 185 | } 186 | 187 | public static DoubleVector gradientDescend(IFunctionND function, DoubleVector xStart) { 188 | return gradientDescend(function, xStart, NumericCommon.NUMERIC_ACCURACY_MIDDLE, NumericCommon.ITERATIONS_COUNT_HIGH); 189 | } 190 | 191 | public static DoubleVector conjGradientDescend(IFunctionND function, DoubleVector xStart, double eps, int maxIterations) { 192 | DoubleVector x_i = new DoubleVector(xStart); 193 | DoubleVector x_i_1 = new DoubleVector(xStart); 194 | DoubleVector s_i = DoubleVector.gradient(function, xStart, eps).mul(-1.0), s_i_1; 195 | double omega; 196 | int iteration = 0; 197 | for (; iteration != maxIterations; iteration++) { 198 | x_i_1 = DoubleVector.add(x_i, s_i); 199 | x_i_1 = biSect(function, x_i, x_i_1, eps, maxIterations); 200 | if (DoubleVector.distance(x_i_1, x_i) < 2 * eps) break; 201 | s_i_1 = DoubleVector.gradient(function, x_i_1, eps); 202 | omega = Math.pow((s_i_1).magnitude(), 2) / Math.pow((s_i).magnitude(), 2); 203 | s_i.mul(omega).sub(s_i_1); 204 | x_i = x_i_1; 205 | } 206 | 207 | if (NumericCommon.SHOW_DEBUG_LOG) 208 | System.out.printf("Conj gradient descend iterations number : %s\n", iteration + 1); 209 | return DoubleVector.add(x_i_1, x_i).mul(0.5); 210 | } 211 | 212 | public static DoubleVector conjGradientDescend(IFunctionND function, DoubleVector xStart, double eps) { 213 | return conjGradientDescend(function, xStart, eps, NumericCommon.ITERATIONS_COUNT_HIGH); 214 | } 215 | 216 | public static DoubleVector conjGradientDescend(IFunctionND function, DoubleVector xStart) { 217 | return conjGradientDescend(function, xStart, NumericCommon.NUMERIC_ACCURACY_MIDDLE, NumericCommon.ITERATIONS_COUNT_HIGH); 218 | } 219 | 220 | //////////////////// 221 | /// Lab. work #4 /// 222 | //////////////////// 223 | public static DoubleVector newtoneRaphson(IFunctionND function, DoubleVector xStart, double eps, int maxIterations) { 224 | DoubleVector x_i = new DoubleVector(xStart); 225 | DoubleVector x_i_1 = new DoubleVector(xStart); 226 | int iteration = -1; 227 | for (; iteration != maxIterations; iteration++) { 228 | DoubleMatrix invHessian = Objects.requireNonNull(DoubleMatrix.invert(DoubleMatrix.hessian(function, x_i, eps))); 229 | x_i_1 = DoubleVector.sub(x_i, DoubleMatrix.mul(invHessian, DoubleVector.gradient(function, x_i, eps))); 230 | // Метод работает, но условие снизу не отрабатывает 231 | if (DoubleVector.distance(x_i_1, x_i) < 2 * eps) break; 232 | x_i = x_i_1; 233 | } 234 | 235 | if (NumericCommon.SHOW_DEBUG_LOG) 236 | System.out.printf("Newtone - Raphson iterations number : %s\n", iteration + 1); 237 | return DoubleVector.add(x_i_1, x_i).mul(0.5); 238 | } 239 | 240 | public static DoubleVector newtoneRaphson(IFunctionND function, DoubleVector xStart, double eps) { 241 | return newtoneRaphson(function, xStart, eps, NumericCommon.ITERATIONS_COUNT_LOW); 242 | } 243 | 244 | public static DoubleVector newtoneRaphson(IFunctionND function, DoubleVector xStart) { 245 | return newtoneRaphson(function, xStart, NumericCommon.NUMERIC_ACCURACY_MIDDLE, NumericCommon.ITERATIONS_COUNT_LOW); 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /Java/OptimizationMethods/src/main/java/OneDimensional.java: -------------------------------------------------------------------------------- 1 | import mathUtils.functionalInterfaces.IFunction1D; 2 | import mathUtils.NumericCommon; 3 | 4 | public final class OneDimensional { 5 | //////////////////// 6 | /// Lab. work #1 /// 7 | //////////////////// 8 | public static double biSect(IFunction1D function, double left, double right, final double eps, final int maxIterations) { 9 | if (left > right) { 10 | final double tmp = left; 11 | left = right; 12 | right = tmp; 13 | } 14 | double center; 15 | int iteration = 0; 16 | for (; iteration != maxIterations && Math.abs(right - left) > 2 * eps; iteration++) { 17 | center = (right + left) * 0.5; 18 | if (function.call(center + 1e-1 * eps) > function.call(center - 1e-1 * eps)) 19 | right = center; 20 | else 21 | left = center; 22 | } 23 | if (NumericCommon.SHOW_ZERO_ORDER_METHODS_DEBUG_LOG) { 24 | System.out.printf("BiSect::function probes count : %s\n", 2 * iteration); 25 | System.out.printf("BiSect::function arg range : %s\n", right - left); 26 | } 27 | return (right + left) * 0.5; 28 | } 29 | 30 | public static double biSect(IFunction1D function, double left, double right, double eps) { 31 | return biSect(function, left, right, eps, NumericCommon.ITERATIONS_COUNT_HIGH); 32 | } 33 | 34 | public static double biSect(IFunction1D function, double left, double right) { 35 | return biSect(function, left, right, NumericCommon.NUMERIC_ACCURACY_MIDDLE, NumericCommon.ITERATIONS_COUNT_HIGH); 36 | } 37 | 38 | public static double goldenRatio(IFunction1D function, double left, double right, double eps, int maxIterations) { 39 | if (left > right) { 40 | final double tmp = left; 41 | left = right; 42 | right = tmp; 43 | } 44 | double x_l, x_r, f_l, f_r; 45 | int iteration = 0; 46 | x_l = right - (right - left) * NumericCommon.PSI; 47 | x_r = left + (right - left) * NumericCommon.PSI; 48 | f_l = function.call(x_l); 49 | f_r = function.call(x_r); 50 | for (; iteration != maxIterations && Math.abs(right - left) > 2 * eps; iteration++) { 51 | if (f_l > f_r) { 52 | left = x_l; 53 | x_l = x_r; 54 | f_l = f_r; 55 | x_r = left + (right - left) * NumericCommon.PSI; 56 | f_r = function.call(x_r); 57 | } else { 58 | right = x_r; 59 | x_r = x_l; 60 | f_r = f_l; 61 | x_l = right - (right - left) * NumericCommon.PSI; 62 | f_l = function.call(x_l); 63 | } 64 | } 65 | 66 | if (NumericCommon.SHOW_ZERO_ORDER_METHODS_DEBUG_LOG) { 67 | System.out.printf("goldenRatio::function probes count : %s\n", 2 + iteration); 68 | System.out.printf("goldenRatio::function arg range : %s\n", right - left); 69 | } 70 | return (right + left) * 0.5; 71 | } 72 | 73 | public static double goldenRatio(IFunction1D function, double left, double right, double eps) { 74 | return goldenRatio(function, left, right, eps, NumericCommon.ITERATIONS_COUNT_HIGH); 75 | } 76 | 77 | public static double goldenRatio(IFunction1D function, double left, double right) { 78 | return goldenRatio(function, left, right, NumericCommon.NUMERIC_ACCURACY_MIDDLE, NumericCommon.ITERATIONS_COUNT_HIGH); 79 | } 80 | 81 | public static double fibonacci(IFunction1D function, double left, double right, double eps) { 82 | if (left > right) { 83 | final double tmp = left; 84 | left = right; 85 | right = tmp; 86 | } 87 | double x_l, x_r, f_l, f_r, condition, fib_t, fib_1 = 1.0, fib_2 = 1.0; 88 | int iterations = 0; 89 | condition = (right - left) / eps; 90 | while (fib_2 < condition) { 91 | iterations++; 92 | fib_t = fib_1; 93 | fib_1 = fib_2; 94 | fib_2 += fib_t; 95 | } 96 | x_l = left + (right - left) * ((fib_2 - fib_1) / fib_2); 97 | x_r = left + (right - left) * (fib_1 / fib_2); 98 | f_l = function.call(x_l); 99 | f_r = function.call(x_r); 100 | for (int index = iterations; index > 0; index--) { 101 | fib_t = fib_2 - fib_1; 102 | fib_2 = fib_1; 103 | fib_1 = fib_t; 104 | if (f_l > f_r) { 105 | left = x_l; 106 | f_l = f_r; 107 | x_l = x_r; 108 | x_r = left + (right - left) * (fib_1 / fib_2); 109 | f_r = function.call(x_r); 110 | } else { 111 | right = x_r; 112 | x_r = x_l; 113 | f_r = f_l; 114 | x_l = left + (right - left) * ((fib_2 - fib_1) / fib_2); 115 | f_l = function.call(x_l); 116 | } 117 | } 118 | if (NumericCommon.SHOW_ZERO_ORDER_METHODS_DEBUG_LOG) { 119 | System.out.printf("fibonacci::function probes count : %s\n", 2 + iterations); 120 | System.out.printf("fibonacci::function arg range : %s\n", right - left); 121 | } 122 | return (right + left) * 0.5; 123 | } 124 | 125 | public static double fibonacci(IFunction1D function, double left, double right) { 126 | return fibonacci(function, left, right, NumericCommon.NUMERIC_ACCURACY_MIDDLE); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /Java/OptimizationMethods/src/main/java/SimplexIO.java: -------------------------------------------------------------------------------- 1 | public class SimplexIO { 2 | } 3 | -------------------------------------------------------------------------------- /Java/OptimizationMethods/src/main/java/mathUtils/DoubleVector.java: -------------------------------------------------------------------------------- 1 | package mathUtils; 2 | import mathUtils.functionalInterfaces.IFunctionND; 3 | 4 | 5 | @SuppressWarnings("all") 6 | public final class DoubleVector extends TemplateVector{ 7 | public DoubleVector(int cap, double fill_value) { 8 | super(cap); 9 | fill(i -> fill_value); 10 | } 11 | 12 | public DoubleVector(int cap) { 13 | this(cap, 0.0); 14 | } 15 | 16 | public DoubleVector(DoubleVector other) { 17 | super(other); 18 | } 19 | 20 | public DoubleVector(Double... args) { 21 | super(args); 22 | } 23 | 24 | public DoubleVector(Iterable other) { 25 | super(other); 26 | } 27 | 28 | protected DoubleVector(Slice slice, DoubleVector other) { 29 | super(slice, other); 30 | } 31 | 32 | public DoubleVector get(Slice slice) 33 | { 34 | return new DoubleVector(slice, this); 35 | } 36 | 37 | public double magnitude() { 38 | return Math.sqrt(reduce(this, (acc, val) -> acc + val * val, 0.0)); 39 | } 40 | 41 | public DoubleVector normalize() { 42 | double inv_mag = 1.0 / magnitude(); 43 | apply(v -> v * inv_mag); 44 | return this; 45 | } 46 | 47 | public DoubleVector normalized() { 48 | return new DoubleVector(this).normalize(); 49 | } 50 | 51 | public double dot(final DoubleVector other) { 52 | if (size() != other.size()) throw new RuntimeException("Dot product :: this.Size()!= other.Size()"); 53 | return reduce(combine(this, other, (l, r) -> l * r), Double::sum, 0.0); 54 | } 55 | 56 | @Override 57 | public String toString() { 58 | if(NumericCommon.NUMBER_RATIONAL_FORMAT) 59 | { 60 | return String.format("{%s}", String.join("; ", 61 | DoubleVector.map(this, v -> String.format("%8s", 62 | NumericUtils.toRationalStr(v, false))))); 63 | } 64 | return String.format("{%s}", String.join("; ", 65 | DoubleVector.map(this, v -> String.format("%8s", String.format("%.4f", v))))); 66 | } 67 | 68 | /** 69 | * Эквивалент this += other, где other может иметь типы double или DoubleVector 70 | */ 71 | public DoubleVector add(double other) { 72 | apply(v -> v + other); 73 | return this; 74 | } 75 | 76 | public DoubleVector add(final DoubleVector other) { 77 | if (size() != other.size()) throw new RuntimeException("Vectors add :: this.Size()!= other.Size()"); 78 | combine(other, Double::sum); 79 | return this; 80 | } 81 | 82 | /** 83 | * Эквивалент this -= other, где other может иметь типы double или DoubleVector 84 | */ 85 | public DoubleVector sub(double other) { 86 | apply(v -> v - other); 87 | return this; 88 | } 89 | 90 | public DoubleVector sub(final DoubleVector other) { 91 | if (size() != other.size()) throw new RuntimeException("Vectors sub :: this.Size()!= other.Size()"); 92 | combine(other, (l, r) -> l - r); 93 | return this; 94 | } 95 | 96 | /** 97 | * Эквивалент this *= other, где other может иметь типы double или DoubleVector 98 | */ 99 | public DoubleVector mul(double other) { 100 | apply(v -> v * other); 101 | return this; 102 | } 103 | 104 | public DoubleVector mul(final DoubleVector other) { 105 | if (size() != other.size()) throw new RuntimeException("Vectors add :: this.Size()!= other.Size()"); 106 | combine(other, (l, r) -> l * r); 107 | return this; 108 | } 109 | 110 | /** 111 | * Эквивалент this /= other, где other может иметь типы double или DoubleVector 112 | */ 113 | public DoubleVector div(double other) { 114 | apply(v -> v / other); 115 | return this; 116 | } 117 | 118 | public DoubleVector div(final DoubleVector other) { 119 | if (size() != other.size()) throw new RuntimeException("Vectors sub :: this.Size()!= other.Size()"); 120 | combine(other, (l, r) -> l / r); 121 | return this; 122 | } 123 | 124 | /** 125 | * Эквивалент left + right, где left и right могут иметь типы double или DoubleVector 126 | */ 127 | public static DoubleVector add(final DoubleVector left, double right) { 128 | return new DoubleVector(combine(left, right, Double::sum)); 129 | } 130 | 131 | public static DoubleVector add(double left, final DoubleVector right) { 132 | return new DoubleVector(combine(left, right, Double::sum)); 133 | } 134 | 135 | public static DoubleVector add(final DoubleVector left, final DoubleVector right) { 136 | if (left.size() != right.size()) throw new RuntimeException("Vectors sum :: this.Size()!= other.Size()"); 137 | return new DoubleVector(combine(left, right, Double::sum)); 138 | } 139 | 140 | /** 141 | * Эквивалент left - right, где left и right могут иметь типы double или DoubleVector 142 | */ 143 | public static DoubleVector sub(final DoubleVector left, double right) { 144 | return new DoubleVector(combine(left, right, (l, r) -> l - r)); 145 | } 146 | 147 | public static DoubleVector sub(double left, final DoubleVector right) { 148 | return new DoubleVector(combine(left, right, (l, r) -> l - r)); 149 | } 150 | 151 | public static DoubleVector sub(final DoubleVector left, final DoubleVector right) { 152 | if (left.size() != right.size()) throw new RuntimeException("Vectors sub :: this.Size()!= other.Size()"); 153 | return new DoubleVector(combine(left, right, (l, r) -> l - r)); 154 | } 155 | 156 | /** 157 | * Эквивалент left * right, где left и right могут иметь типы double или DoubleVector 158 | */ 159 | public static DoubleVector mul(final DoubleVector left, double right) { 160 | return new DoubleVector(combine(left, right, (l, r) -> l * r)); 161 | } 162 | 163 | public static DoubleVector mul(double left, final DoubleVector right) { 164 | return new DoubleVector(combine(left, right, (l, r) -> l * r)); 165 | } 166 | 167 | public static DoubleVector mul(final DoubleVector left, final DoubleVector right) { 168 | if (left.size() != right.size()) throw new RuntimeException("Vectors sub :: this.Size()!= other.Size()"); 169 | return new DoubleVector(combine(left, right, (l, r) -> l * r)); 170 | } 171 | 172 | /** 173 | * Эквивалент left / right, где left и right могут иметь типы double или DoubleVector 174 | */ 175 | public static DoubleVector div(final DoubleVector left, double right) { 176 | return new DoubleVector(combine(left, right, (l, r) -> l / r)); 177 | } 178 | 179 | public static DoubleVector div(double left, final DoubleVector right) { 180 | return new DoubleVector(combine(left, right, (l, r) -> l / r)); 181 | } 182 | 183 | public static DoubleVector div(final DoubleVector left, final DoubleVector right) { 184 | if (left.size() != right.size()) throw new RuntimeException("Vectors sub :: this.Size()!= other.Size()"); 185 | return new DoubleVector(combine(left, right, (l, r) -> l / r)); 186 | } 187 | 188 | public static DoubleVector direction(final DoubleVector left, final DoubleVector right) { 189 | if (left.size() != right.size()) throw new RuntimeException("Vectors direction :: a.Size()!= b.Size()"); 190 | return sub(right, left).normalize(); 191 | } 192 | 193 | public static double dot(final DoubleVector left, final DoubleVector right) { 194 | return left.dot(right); 195 | } 196 | 197 | public static double partial(IFunctionND func, DoubleVector x, int index, double eps) { 198 | if (x.notInRange(index)) throw new RuntimeException("Partial derivative index out of bounds!"); 199 | x.uncheckedSet(index, x.uncheckedGet(index) + eps); 200 | double f_r = func.call(x); 201 | x.uncheckedSet(index, x.uncheckedGet(index) - 2.0 * eps); 202 | double f_l = func.call(x); 203 | x.uncheckedSet(index, x.uncheckedGet(index) + eps); 204 | return (f_r - f_l) / eps * 0.5; 205 | } 206 | 207 | public static double partial(IFunctionND func, DoubleVector x, int index) { 208 | return partial(func, x, index, NumericCommon.NUMERIC_ACCURACY_MIDDLE); 209 | } 210 | 211 | public static double partial2(IFunctionND func, DoubleVector x, int index_1, int index_2, double eps) { 212 | return partial((arg)->partial(func, arg, index_1, eps), x, index_2, eps); 213 | } 214 | 215 | public static DoubleVector gradient(IFunctionND func, final DoubleVector x, double eps) { 216 | DoubleVector df = new DoubleVector(x.size()); 217 | df.applyEnumerate((i, v) -> partial(func, x, i, eps)); 218 | return df; 219 | } 220 | 221 | public static double partial2(IFunctionND func, final DoubleVector x, int index_1, int index_2) { 222 | return partial2(func, x, index_1, index_2, NumericCommon.NUMERIC_ACCURACY_MIDDLE); 223 | } 224 | 225 | public static DoubleVector gradient(IFunctionND func, final DoubleVector x) { 226 | return gradient(func, x, NumericCommon.NUMERIC_ACCURACY_MIDDLE); 227 | } 228 | 229 | public static double distance(final DoubleVector lhs, final DoubleVector rhs) { 230 | if (lhs.size() != rhs.size()) throw new RuntimeException("Distance :: this.Size()!= other.Size()"); 231 | return Math.sqrt(reduce(DoubleVector.combine(lhs, rhs, (l, r) -> (l - r) * (l - r)), Double::sum, 0.0)); 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /Java/OptimizationMethods/src/main/java/mathUtils/NumericCommon.java: -------------------------------------------------------------------------------- 1 | package mathUtils; 2 | 3 | @SuppressWarnings("all") 4 | public class NumericCommon { 5 | public static final double PHI = 1.61803398874989484820; 6 | public static final double PSI = 0.6180339887498948; 7 | public static final double NUMERIC_ACCURACY_MIDDLE = 1e-6; 8 | public static final double NUMERIC_ACCURACY_LOW = 1e-3; 9 | public static final double NUMERIC_ACCURACY_HIGH = 1e-9; 10 | public static final int ZERO_ORDER_METHODS_MAX_ITERATIONS_COUNT = 1000; 11 | public static final int ITERATIONS_COUNT_HIGH = 1000; 12 | public static final int ITERATIONS_COUNT_MIDDLE = 500; 13 | public static final int ITERATIONS_COUNT_LOW = 100; 14 | public static boolean SHOW_ZERO_ORDER_METHODS_DEBUG_LOG = false; 15 | public static boolean SHOW_DEBUG_LOG = false; 16 | public static boolean SHOW_SIMPLEX_DEBUG_LOG = false; 17 | public static boolean SHOW_MATRIX_DEBUG_LOG = false; 18 | public static boolean NUMBER_RATIONAL_FORMAT = true; 19 | // public static boolean ITERATOR_BASED_IMPLEMENTATION = true; 20 | } 21 | -------------------------------------------------------------------------------- /Java/OptimizationMethods/src/main/java/mathUtils/NumericUtils.java: -------------------------------------------------------------------------------- 1 | package mathUtils; 2 | import mathUtils.functionalInterfaces.IFunction1D; 3 | import mathUtils.functionalInterfaces.IFunctionND; 4 | 5 | 6 | @SuppressWarnings("all") 7 | public class NumericUtils { 8 | 9 | private static int getFactorial(int f) { 10 | int result = 1; 11 | for (int i = 1; i <= f; i++) { 12 | result = result * i; 13 | } 14 | return result; 15 | } 16 | 17 | private static int[] calculateFactorials() { 18 | int[] factorials = new int[128]; 19 | for (int i = 0; i < 128; i++) { 20 | factorials[i] = getFactorial(i + 1); 21 | } 22 | return factorials; 23 | } 24 | 25 | public static final int[] factorialsTable128 = calculateFactorials(); 26 | 27 | public static final IFunction1D testFunc1d = NumericUtils::testFunc1D; 28 | 29 | public static final IFunctionND testFunc2d = NumericUtils::_testFunc2D; 30 | 31 | public static final IFunctionND testFuncNd = NumericUtils::_testFuncND; 32 | 33 | public static int clamp(int value, int min, int max) { 34 | return Math.min(Math.max(min, value), max); 35 | } 36 | 37 | public static float clamp(float value, float min, float max) { 38 | return Math.min(Math.max(min, value), max); 39 | } 40 | 41 | public static double clamp(double value, double min, double max) { 42 | return Math.min(Math.max(min, value), max); 43 | } 44 | 45 | public static double testFunc1D(double x) { 46 | return (x - 5) * (x - 2); // min at point x = 3.5 47 | } 48 | 49 | private static double _testFunc2D(DoubleVector x) { 50 | return (x.get(0) - 5) * x.get(0) + (x.get(1) - 3) * x.get(1); // min at point x = 2.5, y = 1.5 51 | } 52 | 53 | private static double _testFuncND(DoubleVector x) { 54 | double val = 0.0; 55 | 56 | for (int i = 0; i < x.size(); i++) { 57 | val += (x.get(i) - i) * x.get(i); 58 | } 59 | return val; // min at point x_i = i/2, i from 0 to x.Size-1 60 | } 61 | 62 | public static int[] fibonacciNumbers(int index) { 63 | if (index < 1) return new int[]{0}; 64 | if (index < 2) return new int[]{0, 1}; 65 | int[] res = new int[index]; 66 | res[0] = 0; 67 | res[1] = 1; 68 | for (int i = 2; i < index; i++) res[i] = res[i - 1] + res[i - 2]; 69 | return res; 70 | } 71 | 72 | public static int[] closestFibonacciPair(double value) { 73 | int f_n = 0; 74 | int f_n_1; 75 | if (value < 1) return new int[]{0}; 76 | f_n_1 = 1; 77 | if (value < 2) return new int[]{0, 1}; 78 | int f_tmp; 79 | while (f_n < value) { 80 | f_tmp = f_n; 81 | f_n = f_n_1; 82 | f_n_1 += f_tmp; 83 | } 84 | return new int[]{f_n, f_n_1}; 85 | } 86 | 87 | /** 88 | * Конвертирует десятичную запись числа в рациональную, 89 | * например, 1.666 -> [1, 2, 3] 90 | *

91 | * Converts decimal representation of number into rational, 92 | * ex. 1.666 -> [1, 2, 3] 93 | * 94 | * @param value исходное число | original number 95 | * @param max_den максимально допустимый знаменатель | max denominator of number 96 | * @return int[]{integer_part, numerator, denominator} 97 | */ 98 | public static int[] decimalToRational(double value, int max_den) { 99 | long m00 = 1; 100 | long m01 = 0; 101 | long m10 = 0; 102 | long m11 = 1; 103 | 104 | int[] number = new int[3]; 105 | 106 | long ai; 107 | 108 | double x; 109 | 110 | int sign = value >= 0 ? 1 : -1; 111 | 112 | x = Math.abs(value); 113 | 114 | long t; 115 | 116 | while (m10 * (ai = (long) x) + m11 <= max_den) { 117 | t = m00 * ai + m01; 118 | 119 | m01 = m00; 120 | m00 = t; 121 | 122 | t = m10 * ai + m11; 123 | 124 | m11 = m10; 125 | m10 = t; 126 | if (x == (double) ai) { 127 | break; 128 | } // AF: division by zero 129 | x = 1 / (x - (double) ai); 130 | if (x > (double) 0x7FFFFFFF) { 131 | break; 132 | } // AF: representation failure 133 | } 134 | 135 | if ((number[0] = (int) (m00 / m10)) != 0) { 136 | number[1] = (int) (m00 - number[0] * m10); 137 | 138 | number[0] *= sign; 139 | 140 | number[2] = (int) m10; 141 | 142 | return number; 143 | } 144 | number[1] = (int) (sign * m00); 145 | 146 | number[2] = (int) m10; 147 | 148 | return number; 149 | } 150 | 151 | public static int[] decimalToRational(double value) { 152 | return decimalToRational(value, NumericCommon.ITERATIONS_COUNT_HIGH); 153 | } 154 | 155 | private static String toRationalStr(int _int, int _num, int _den, boolean fullRational) { 156 | // 0 _int number[0] 157 | // 1 _num number[1] 158 | // 2 _den number[2] 159 | if (_num == 0) return String.valueOf(_int); 160 | if (_int == 0) return String.format("%s/%s", _num, _den); 161 | if (fullRational) { 162 | return String.format("%s/%s", 163 | (_num + Math.abs(_int) * _den) * (_int >= 0 ? 1 : -1), _den); 164 | } 165 | return String.format("%s %s/%s", _int, _num, _den); 166 | } 167 | 168 | public static String toRationalStr(double value, boolean fullRational) { 169 | int[] number = NumericUtils.decimalToRational(value); 170 | return toRationalStr(number[0], number[1], number[2], fullRational); 171 | } 172 | 173 | public static String toRationalStr(double value) { 174 | return toRationalStr(value, true); 175 | } 176 | 177 | public static String toRationalStr(DoubleVector value, boolean fullRational) { 178 | return String.format("{ %s }", 179 | String.join("; ", DoubleVector.map(value, v -> toRationalStr(v, fullRational)))); 180 | } 181 | 182 | public static String toRationalStr(DoubleVector value) { 183 | return toRationalStr(value, false); 184 | } 185 | 186 | public static class RationalNumber { 187 | private final int _numerator; 188 | private final int _denominator; 189 | private final int _intPart; 190 | 191 | @Override 192 | public boolean equals(Object other) { 193 | if (this == other) return true; 194 | if (other == null || getClass() != other.getClass()) return false; 195 | return equals((RationalNumber) other); 196 | } 197 | 198 | public boolean equals(RationalNumber number) { 199 | if (number.numerator() != numerator()) return false; 200 | if (number.denominator() != denominator()) return false; 201 | if (number.intPart() != intPart()) return false; 202 | return true; 203 | } 204 | 205 | @Override 206 | public String toString() { 207 | return toRationalStr(intPart(), numerator(), denominator(), false); 208 | } 209 | 210 | public int numerator() { 211 | return _numerator; 212 | } 213 | 214 | public int denominator() { 215 | return _denominator; 216 | } 217 | 218 | public int intPart() { 219 | return _intPart; 220 | } 221 | 222 | public RationalNumber(final int numerator, final int denominator, final int intPart) { 223 | this._numerator = numerator; 224 | this._denominator = denominator; 225 | this._intPart = intPart; 226 | } 227 | 228 | public RationalNumber(final RationalNumber other) { 229 | this(other.numerator(), other.denominator(), other.intPart()); 230 | } 231 | 232 | public RationalNumber(final double value) { 233 | int[] number = decimalToRational(value); 234 | this._intPart = number[0]; 235 | this._numerator = number[1]; 236 | this._denominator = number[2]; 237 | } 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /Java/OptimizationMethods/src/main/java/mathUtils/PenaltyFunction.java: -------------------------------------------------------------------------------- 1 | package mathUtils; 2 | 3 | import mathUtils.functionalInterfaces.IFunctionND; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | 7 | 8 | public final class PenaltyFunction implements IFunctionND { 9 | private int _penaltyFunctionMixMode; 10 | 11 | private final Set _boundaries; 12 | 13 | private IFunctionND _target; 14 | 15 | public int penaltyFunctionMixMode(){ 16 | return _penaltyFunctionMixMode; 17 | } 18 | 19 | public void penaltyFunctionMixMode(int value){ 20 | _penaltyFunctionMixMode = value % 4; 21 | } 22 | 23 | public IFunctionND target(){ 24 | return _target; 25 | } 26 | 27 | public IFunctionND target(IFunctionND target){ 28 | return _target = target; 29 | } 30 | 31 | public boolean appendBound(IFunctionND bound) { 32 | if(_boundaries.contains(bound)) 33 | return false; 34 | _boundaries.add(bound); 35 | return true; 36 | } 37 | 38 | public boolean removeBound(IFunctionND bound) { 39 | if(!_boundaries.contains(bound)) 40 | return false; 41 | _boundaries.remove(bound); 42 | return true; 43 | } 44 | 45 | public boolean appendBoundaries(IFunctionND... boundaries) { 46 | boolean result = false; 47 | for (IFunctionND bound: boundaries) 48 | result |= appendBound(bound); 49 | return result; 50 | } 51 | 52 | public boolean removeBoundaries(IFunctionND... boundaries) { 53 | boolean result = false; 54 | for (IFunctionND bound: boundaries) 55 | result |= removeBound(bound); 56 | return result; 57 | } 58 | 59 | public PenaltyFunction(){ 60 | _boundaries = new HashSet<>(); 61 | _target = v -> (v.dot(v)); 62 | } 63 | 64 | @Override 65 | public double call(final DoubleVector arg) { 66 | double result = target() == null ? 0.0 : target().call(arg); 67 | switch (penaltyFunctionMixMode()){ 68 | case 1 /*MUL*/ : for (IFunctionND bound: _boundaries) result *= bound.call(arg); break; 69 | case 2 /*MAX*/ : for (IFunctionND bound: _boundaries) result = Math.max(result, bound.call(arg)); break; 70 | case 3 /*MIN*/ : for (IFunctionND bound: _boundaries) result = Math.min(result, bound.call(arg)); break; 71 | default: /*SUM*/ for (IFunctionND bound: _boundaries) result += bound.call(arg); break; 72 | } 73 | return result; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Java/OptimizationMethods/src/main/java/mathUtils/Slice.java: -------------------------------------------------------------------------------- 1 | package mathUtils; 2 | 3 | @SuppressWarnings("all") 4 | public final class Slice { 5 | private final int _end; 6 | private final int _begin; 7 | private final int _step; 8 | //exclusive index 9 | public int end() { 10 | return _end; 11 | } 12 | //inclusive index 13 | public int begin() { 14 | return _begin; 15 | } 16 | 17 | public int step() { 18 | return _step; 19 | } 20 | 21 | public Slice() { 22 | this(0, 0, 1); 23 | } 24 | 25 | public Slice(final int begin, final int end) { 26 | this(begin, end, 1); 27 | } 28 | 29 | public Slice(final int begin, final int end, final int step) { 30 | this._step = step; // == 0 ? 1 : step; 31 | this._begin = begin; 32 | this._end = end; 33 | } 34 | 35 | @Override 36 | public boolean equals(Object o) { 37 | if (this == o) return true; 38 | if (o == null || getClass() != o.getClass()) return false; 39 | return equals((Slice) o); 40 | } 41 | 42 | public boolean equals(Slice slice) { 43 | if(slice.begin() != begin())return false; 44 | if(slice.end() != end() )return false; 45 | if(slice.step() != step())return false; 46 | return true; 47 | } 48 | 49 | @Override 50 | public String toString(){ 51 | return step() == 1 ? String.format("%s:%s", begin(), end()) : String.format("%s:%s:%s", begin(), end(), step()); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Java/OptimizationMethods/src/main/java/mathUtils/functionalInterfaces/ICombineFunction.java: -------------------------------------------------------------------------------- 1 | package mathUtils.functionalInterfaces; 2 | 3 | @FunctionalInterface 4 | public interface ICombineFunction { 5 | T2 call(T1 left, T1 right); 6 | } 7 | -------------------------------------------------------------------------------- /Java/OptimizationMethods/src/main/java/mathUtils/functionalInterfaces/IConditionFunction.java: -------------------------------------------------------------------------------- 1 | package mathUtils.functionalInterfaces; 2 | 3 | @FunctionalInterface 4 | public interface IConditionFunction { 5 | boolean call(T element); 6 | } 7 | -------------------------------------------------------------------------------- /Java/OptimizationMethods/src/main/java/mathUtils/functionalInterfaces/IFillFunction.java: -------------------------------------------------------------------------------- 1 | package mathUtils.functionalInterfaces; 2 | 3 | @FunctionalInterface 4 | public interface IFillFunction{ 5 | T call(int index); 6 | } -------------------------------------------------------------------------------- /Java/OptimizationMethods/src/main/java/mathUtils/functionalInterfaces/IForEachApplyFunction.java: -------------------------------------------------------------------------------- 1 | package mathUtils.functionalInterfaces; 2 | 3 | @FunctionalInterface 4 | public interface IForEachApplyFunction{ 5 | T call(T element); 6 | } 7 | -------------------------------------------------------------------------------- /Java/OptimizationMethods/src/main/java/mathUtils/functionalInterfaces/IForEnumerateApplyFunction.java: -------------------------------------------------------------------------------- 1 | package mathUtils.functionalInterfaces; 2 | 3 | @FunctionalInterface 4 | public interface IForEnumerateApplyFunction{ 5 | T call(int elementIndex, T element); 6 | } 7 | -------------------------------------------------------------------------------- /Java/OptimizationMethods/src/main/java/mathUtils/functionalInterfaces/IFunction1D.java: -------------------------------------------------------------------------------- 1 | package mathUtils.functionalInterfaces; 2 | 3 | @FunctionalInterface 4 | public interface IFunction1D{ 5 | double call(double arg); 6 | } 7 | -------------------------------------------------------------------------------- /Java/OptimizationMethods/src/main/java/mathUtils/functionalInterfaces/IFunctionND.java: -------------------------------------------------------------------------------- 1 | package mathUtils.functionalInterfaces; 2 | import mathUtils.DoubleVector; 3 | 4 | @FunctionalInterface 5 | public interface IFunctionND{ 6 | double call(final DoubleVector arg); 7 | } 8 | -------------------------------------------------------------------------------- /Java/OptimizationMethods/src/main/java/mathUtils/functionalInterfaces/IMapFunction.java: -------------------------------------------------------------------------------- 1 | package mathUtils.functionalInterfaces; 2 | 3 | @FunctionalInterface 4 | public interface IMapFunction{ 5 | T1 call(T2 arg); 6 | } 7 | -------------------------------------------------------------------------------- /Java/OptimizationMethods/src/main/java/mathUtils/functionalInterfaces/IReduceFunction.java: -------------------------------------------------------------------------------- 1 | package mathUtils.functionalInterfaces; 2 | 3 | @FunctionalInterface 4 | public interface IReduceFunction { 5 | T call(T accumulator, T value); 6 | } 7 | -------------------------------------------------------------------------------- /OptimizationMethods.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Python/OptimizationMethods/.idea/OptimizationMethods.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Python/OptimizationMethods/Resources/sm_task.json: -------------------------------------------------------------------------------- 1 | { 2 | "problems": 3 | [ 4 | { 5 | "solve_type": 0, 6 | "weights": 7 | { 8 | "shape" : [2], 9 | "data" : [2.0, 3.0] 10 | }, 11 | "bounds": 12 | { 13 | "shape" : [3], 14 | "data" : [40.0, 28.0, 14.0] 15 | }, 16 | "bounds_matrix": 17 | { 18 | "shape" : [3, 2], 19 | "data" : [-2.0, 6.0, 20 | 3.0, 2.0, 21 | 2.0,-1.0] 22 | }, 23 | "inequalities": [-1, -1, -1] 24 | }, 25 | { 26 | "solve_type": 1, 27 | "weights": 28 | { 29 | "shape" : [2], 30 | "data" : [-2.0, 3.0] 31 | }, 32 | "bounds": 33 | { 34 | "shape" : [3], 35 | "data" : [40.0, 28.0, 14.0] 36 | }, 37 | "bounds_matrix": 38 | { 39 | "shape" : [3, 2], 40 | "data" : [-2.0, 6.0, 41 | 3.0, 2.0, 42 | 2.0,-1.0] 43 | }, 44 | "inequalities": [-1, -1, -1] 45 | }, 46 | { 47 | "solve_type": 0, 48 | "weights": 49 | { 50 | "shape" : [2], 51 | "data" : [2.0, 1.0] 52 | }, 53 | "bounds": 54 | { 55 | "shape" : [3], 56 | "data" : [40.0, 28.0, 14.0] 57 | }, 58 | "bounds_matrix": 59 | { 60 | "shape" : [3, 2], 61 | "data" : [-2.0, 6.0, 62 | 3.0, 2.0, 63 | 2.0,-1.0] 64 | }, 65 | "inequalities": [1, 1, 1] 66 | }, 67 | { 68 | "solve_type": 1, 69 | "weights": 70 | { 71 | "shape" : [2], 72 | "data" : [-2.0, -1.0] 73 | }, 74 | "bounds": 75 | { 76 | "shape" : [3], 77 | "data" : [40.0, 28.0, 14.0] 78 | }, 79 | "bounds_matrix": 80 | { 81 | "shape" : [3, 2], 82 | "data" : [-2.0, 6.0, 83 | 3.0, 2.0, 84 | 2.0,-1.0] 85 | }, 86 | "inequalities": [1, 1, 1] 87 | }, 88 | { 89 | "solve_type": 1, 90 | "weights": 91 | { 92 | "shape" : [2], 93 | "data" : [2.0, 3.0] 94 | }, 95 | "bounds": 96 | { 97 | "shape" : [3], 98 | "data" : [40.0, 28.0, 14.0] 99 | }, 100 | "bounds_matrix": 101 | { 102 | "shape" : [3, 2], 103 | "data" : [-2.0, 6.0, 104 | 3.0, 2.0, 105 | 2.0,-1.0] 106 | }, 107 | "inequalities": [0, 0, 0] 108 | } 109 | ] 110 | } -------------------------------------------------------------------------------- /Python/OptimizationMethods/main.py: -------------------------------------------------------------------------------- 1 | # This is a sample Python script. 2 | 3 | # Press Shift+F10 to execute it or replace it with your code. 4 | # Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings. 5 | 6 | 7 | def print_hi(name): 8 | # Use a breakpoint in the code line below to debug your script. 9 | print(f'Hi, {name}') # Press Ctrl+F8 to toggle the breakpoint. 10 | 11 | 12 | # Press the green button in the gutter to run the script. 13 | if __name__ == '__main__': 14 | print_hi('kurva') 15 | 16 | # See PyCharm help at https://www.jetbrains.com/help/pycharm/ 17 | -------------------------------------------------------------------------------- /Python/OptimizationMethods/simplex.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | from typing import List, Tuple 3 | from fractions import Fraction 4 | import json 5 | 6 | import numpy as np 7 | from numpy import ndarray 8 | 9 | SOLVE_MAX = 0 10 | SOLVE_MIN = 1 11 | LESS_EQUAL = -1 12 | EQUAL = 0 13 | MORE_EQUAL = 1 14 | CELL_WIDTH = 11 15 | INEQUALITIES_STR = ['<= ', ' = ', '>= '] 16 | 17 | 18 | def _as_frac(value: float): 19 | f = Fraction(value).limit_denominator(50) 20 | i, d, n = f.numerator // f.denominator, f.denominator, f.numerator 21 | if n == 0: 22 | return f"{n}" 23 | if i == 0: 24 | return f"{n}/{d}" 25 | if i == n * d: 26 | return f"{i}" 27 | return f"{i} {n - d * i}/{d}" 28 | 29 | 30 | class SimplexStep(namedtuple('SimplexStep', 'main_row, main_col, basis_args, simplex_table')): 31 | 32 | def __new__(cls, main_row: int, main_col: int, basis_args: np.ndarray, simplex_table: np.ndarray): 33 | return super().__new__(cls, main_row, main_col, basis_args, simplex_table) 34 | 35 | @property 36 | def main_element(self): 37 | if self.main_row == -1 or self.main_col == -1: 38 | return None 39 | return self.simplex_table[self.main_row, self.main_col] 40 | 41 | def __str__(self): 42 | """ 43 | Создаёт строковое представление симплекс таблицы. 44 | :return: строковое представление симплекс таблицы, лол. 45 | """ 46 | def _xi(i): 47 | return f"x{i}" 48 | 49 | rows, cols = self.simplex_table.shape 50 | main_element = self.main_element 51 | table = [f"a[{self.main_row + 1:^3},{self.main_col + 1:^3}] = ", 52 | f"{_as_frac(main_element) if main_element is not None else 'None':<7}\n", 53 | f" {'_' * (CELL_WIDTH * (cols + 1) + cols)}\n", f"|{'_' * CELL_WIDTH}|", 54 | '|'.join(f'{_xi(i + 1):_^{CELL_WIDTH}}' for i in range(cols - 1)) + f"|{'b':_^{CELL_WIDTH}}|\n"] 55 | 56 | for arg_id, row in zip(self.basis_args.flat, self.simplex_table): 57 | table.append(f"|{_xi(arg_id + 1):^{CELL_WIDTH}}|" + '|'.join(f'{_as_frac(row_i):^{CELL_WIDTH}}' for row_i in row)) 58 | table.append(f"|\n") 59 | 60 | sim_d = self.simplex_table[-1] 61 | table.append(f"|{'dC':_^{CELL_WIDTH}}|" + '|'.join(f'{_as_frac(v):_^{CELL_WIDTH}}' for v in sim_d) + f"|\n") 62 | return ''.join(v for v in table) 63 | 64 | 65 | class Simplex: 66 | 67 | def __init__(self, weights_v: np.ndarray, bounds_m: np.ndarray, bounds_v: np.ndarray, ineq=None, ref_or_copy=False): 68 | flag, message = Simplex._validate(weights_v, bounds_m, bounds_v) 69 | if not flag: 70 | raise RuntimeError(message) 71 | self._ineq = np.array([LESS_EQUAL for _ in range(bounds_m.shape[0])])if ineq is None else ineq 72 | self._bounds_m = bounds_m if ref_or_copy else np.copy(bounds_m) 73 | self._bounds_v = bounds_v if ref_or_copy else np.copy(bounds_v) 74 | self._weights_v = weights_v if ref_or_copy else np.copy(weights_v) 75 | self._simplex_t = np.copy(self._bounds_m) 76 | # [(переменные в базисе, с-м таблица)] 77 | self._simplex_t_history: List[SimplexStep] = [] 78 | self._basis_args = None # список индексов базисных аргументов 79 | self._f_mod_args = None # список индексов аргументов, которые модифицируют целевую функцию 80 | self._build_sm_table() 81 | 82 | def __str__(self): 83 | def _convert(index, value) -> str: 84 | if index == 0: 85 | return f"-{_as_frac(abs(float(value))):^5} * x{index + 1}" if value < 0 else\ 86 | f" {_as_frac(abs(float(value))):^5} * x{index + 1}" 87 | return f"-{_as_frac(abs(float(value))):^5} * x{index + 1}" if value < 0 else \ 88 | f"+{_as_frac(abs(float(value))):^5} * x{index + 1}" 89 | 90 | problem = ["F(x, c) =", " ".join(f"{_convert(i, v)}" for i, v in enumerate(self._weights_v.flat)), "\n"] 91 | 92 | for (row, b, ineq) in zip(self._bounds_m, self._bounds_v, self._ineq): 93 | s_row = "".join(v for v in [" ", 94 | " ".join(f"{_convert(i, v)}" for (i, v) in enumerate(row.flat)), 95 | " ", 96 | INEQUALITIES_STR[ineq + 1], 97 | f"{_as_frac(float(b))}"]) 98 | problem.append(s_row) 99 | problem.append("\n") 100 | 101 | return "".join(v for v in problem) 102 | 103 | @staticmethod 104 | def _validate(weights: np.ndarray, bounds_mat: np.ndarray, bounds: np.ndarray) -> Tuple[bool, str]: 105 | _n_weights = weights.size 106 | _n_bounds = bounds.size 107 | _m_rows, _m_cols = bounds_mat.shape 108 | if _n_weights != _m_cols: 109 | return False, "Количество столбцов матрицы ограничений не совпадает с количеством весов..." 110 | if _n_bounds != _m_rows: 111 | return False, "Количество строк матрицы ограничений не совпадает с количеством ограничений..." 112 | return True, "" 113 | 114 | @property 115 | def n_bounds(self) -> int: 116 | return self._bounds_v.size 117 | 118 | @property 119 | def n_weights(self) -> int: 120 | return self._weights_v.size 121 | 122 | def _create_col(self, ineq_row: int, ineq: int): 123 | """ 124 | Создаёт новую колонку в см таблице в соответствии с типом ограничения. 125 | :param ineq_row: строка с ограничением. 126 | :param ineq: тип неравенство. 127 | :return: 128 | """ 129 | # last_table = self._s_tables[-1] 130 | if ineq == LESS_EQUAL: 131 | col = [[1.0] if i == ineq_row else [0.0] for i in range(self.n_bounds)] 132 | self._simplex_t = np.hstack((self._simplex_t, np.array(col))) 133 | return self._simplex_t.shape[1] - 1, - 1 134 | 135 | if ineq == EQUAL: 136 | col = [[1.0] if i == ineq_row else [0.0] for i in range(self.n_bounds)] 137 | self._simplex_t = np.hstack((self._simplex_t, np.array(col))) 138 | return self._simplex_t.shape[1] - 1, self._simplex_t.shape[1] - 1 139 | 140 | if ineq == MORE_EQUAL: 141 | col_1 = [[-1.0] if i == ineq_row else [0.0] for i in range(self.n_bounds)] 142 | col_2 = [[1.0] if i == ineq_row else [0.0] for i in range(self.n_bounds)] 143 | self._simplex_t = np.hstack((self._simplex_t, np.array(col_1))) 144 | self._simplex_t = np.hstack((self._simplex_t, np.array(col_2))) 145 | return self._simplex_t.shape[1] - 2, self._simplex_t.shape[1] - 1 146 | 147 | raise RuntimeError("incorrect inequality parameter!") 148 | 149 | def _build_sm_table(self): 150 | """ 151 | Составляет симплекс таблицу на основе прочитанных данных. 152 | :return: 153 | """ 154 | for row_id, b_val in enumerate(self._bounds_v): 155 | if self._bounds_v[row_id] > 0: 156 | continue 157 | self._bounds_m[row_id, :] *= -1.0 158 | self._ineq [row_id] *= -1 159 | 160 | # TODO Добавить проверку на отрицательность элементов вектора B 161 | self._basis_args = np.linspace(0, self.n_bounds - 1, self.n_bounds, dtype=int) 162 | for ineq_id, ineq in enumerate(self._ineq.flat): 163 | basis_arg_id, basis_arg_id_add = self._create_col(ineq_id, ineq) 164 | if basis_arg_id != -1: 165 | self._basis_args[ineq_id] = basis_arg_id 166 | 167 | # текущий размер симплекс таблицы 168 | rows, cols = self._simplex_t.shape 169 | 170 | # симплекс разности (вектор -С) 171 | self._simplex_t = np.vstack((self._simplex_t, np.zeros((1, cols), dtype=float))) 172 | 173 | for index, value in enumerate(self._weights_v.flat): 174 | self._simplex_t[rows, index] = -value 175 | 176 | # симплекс ограничения (вектор B) 177 | self._simplex_t = np.hstack((self._simplex_t, np.zeros((rows + 1, 1), dtype=float))) 178 | 179 | for index, value in enumerate(self._bounds_v.flat): 180 | self._simplex_t[index, cols] = value 181 | 182 | def _get_main_col(self) -> int: 183 | col_id = np.argmin(self._simplex_t[-1, :-1]) 184 | if self._simplex_t[-1, col_id] >= 0: 185 | return -1 186 | return int(col_id) 187 | 188 | def _get_main_row(self, col_id: int) -> int: 189 | delta = 1e32 190 | main_row_id = -1 191 | for row_id, (ai, bi) in enumerate(zip(self._simplex_t[:-1, col_id].flat, self._simplex_t[:-1, -1].flat)): 192 | if ai <= 0.0: 193 | continue 194 | 195 | b_div_a = bi / ai 196 | if delta < b_div_a: 197 | continue 198 | 199 | delta = b_div_a 200 | main_row_id = row_id 201 | 202 | return main_row_id 203 | 204 | def _validate_solution(self) -> bool: 205 | ... 206 | 207 | def _current_solution(self) -> np.ndarray: 208 | ... 209 | 210 | def solve(self): 211 | while True: 212 | main_col = self._get_main_col() 213 | main_row = self._get_main_row(main_col) 214 | # кеширование состояния симплекс таблицы 215 | self._simplex_t_history.append(SimplexStep(main_row, main_col, 216 | np.copy(self._basis_args), 217 | np.copy(self._simplex_t))) 218 | if main_col == -1: 219 | break 220 | if main_row == -1: 221 | break 222 | main_elem = self._simplex_t[main_row, main_col] 223 | self._basis_args[main_row] = main_col 224 | self._simplex_t[main_row, :] /= main_elem 225 | for row_id in range(self._simplex_t.shape[0]): 226 | if row_id == main_row: 227 | continue 228 | self._simplex_t[row_id, :] -= self._simplex_t[main_row, :] * self._simplex_t[row_id, main_col] 229 | 230 | def simplex_steps(self) -> str: 231 | """ 232 | Создаёт строковое представление симплекс таблицы. 233 | :return: строковое представление симплекс таблицы, лол. 234 | """ 235 | return "\n".join(str(v) for v in self._simplex_t_history) 236 | 237 | 238 | def read_simplex(path_to_file: str) -> List[Simplex]: 239 | def _read_array(node): 240 | if 'shape' not in node: 241 | raise RuntimeError('shape is not defined') 242 | shape = tuple(map(int, node['shape'])) 243 | if 'data' not in node: 244 | raise RuntimeError('data is not defined') 245 | array = np.array(list(map(float, node['data'])), dtype=np.float32) 246 | return array.reshape(shape) 247 | 248 | def _read_simplex(json_node) -> Simplex: 249 | solve_type = int(json_node['solve_type']) if 'solve_type' in json_node else SOLVE_MAX 250 | 251 | if 'weights' not in json_node: 252 | raise RuntimeError('weights is not defined') 253 | weights = _read_array(json_node['weights']) 254 | 255 | if 'bounds' not in json_node: 256 | raise RuntimeError('bounds is not defined') 257 | bounds = _read_array(json_node['bounds']) 258 | 259 | if 'bounds_matrix' not in json_node: 260 | raise RuntimeError('bounds_matrix is not defined') 261 | bounds_matrix = _read_array(json_node['bounds_matrix']) 262 | 263 | inequalities = np.array(list(map(int, json_node['inequalities'])), dtype=int) if 'inequalities' in json_node \ 264 | else np.array([LESS_EQUAL for _ in range(bounds_matrix.shape[0])], dtype=int) 265 | return Simplex(weights, bounds_matrix, bounds, inequalities) 266 | 267 | with open(path_to_file, 'rt') as input_file: 268 | raw_data = json.loads(input_file.read()) 269 | if "problems" in raw_data: 270 | return [_read_simplex(node) for node in raw_data['problems']] 271 | return [_read_simplex(raw_data)] 272 | 273 | 274 | simplexes = read_simplex('Resources/sm_task.json') 275 | 276 | # [print(simplex.simplex_table()) for simplex in simplexes] 277 | # print(simplexes[0].simplex_table()) 278 | simplexes[0].solve() 279 | print(simplexes[0]) 280 | print(simplexes[0].simplex_steps()) 281 | -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/.idea/MOLabs.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20 | -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/MultidimensionalMethods/__init__.py: -------------------------------------------------------------------------------- 1 | from .bisect import bisect 2 | from .golden_ratio import golden_ratio 3 | from .fibonacci import fibonacci 4 | from .perCordDescend import perCordDescend 5 | from .gradient_descent import gradient_descent 6 | from .penalty_function import PenaltyFunction 7 | -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/MultidimensionalMethods/__pycache__/__init__.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuryStrelkov/OptimizationMethods/745af24e1c78df1e600e5f87423bf7f3d3ceaf8b/Python/OptimizationMethodsNew/MultidimensionalMethods/__pycache__/__init__.cpython-312.pyc -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/MultidimensionalMethods/__pycache__/bisect.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuryStrelkov/OptimizationMethods/745af24e1c78df1e600e5f87423bf7f3d3ceaf8b/Python/OptimizationMethodsNew/MultidimensionalMethods/__pycache__/bisect.cpython-312.pyc -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/MultidimensionalMethods/__pycache__/fibonacci.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuryStrelkov/OptimizationMethods/745af24e1c78df1e600e5f87423bf7f3d3ceaf8b/Python/OptimizationMethodsNew/MultidimensionalMethods/__pycache__/fibonacci.cpython-312.pyc -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/MultidimensionalMethods/__pycache__/golden_ratio.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuryStrelkov/OptimizationMethods/745af24e1c78df1e600e5f87423bf7f3d3ceaf8b/Python/OptimizationMethodsNew/MultidimensionalMethods/__pycache__/golden_ratio.cpython-312.pyc -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/MultidimensionalMethods/__pycache__/gradient_descent.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuryStrelkov/OptimizationMethods/745af24e1c78df1e600e5f87423bf7f3d3ceaf8b/Python/OptimizationMethodsNew/MultidimensionalMethods/__pycache__/gradient_descent.cpython-312.pyc -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/MultidimensionalMethods/__pycache__/penalty_function.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuryStrelkov/OptimizationMethods/745af24e1c78df1e600e5f87423bf7f3d3ceaf8b/Python/OptimizationMethodsNew/MultidimensionalMethods/__pycache__/penalty_function.cpython-312.pyc -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/MultidimensionalMethods/__pycache__/perCordDescend.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuryStrelkov/OptimizationMethods/745af24e1c78df1e600e5f87423bf7f3d3ceaf8b/Python/OptimizationMethodsNew/MultidimensionalMethods/__pycache__/perCordDescend.cpython-312.pyc -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/MultidimensionalMethods/bisect.py: -------------------------------------------------------------------------------- 1 | from typing import Callable 2 | import numpy as np 3 | 4 | 5 | def bisect(function: Callable[[np.ndarray], float], lhs: np.ndarray, rhs: np.ndarray, 6 | eps: float = 1e-6, n_iters: int = 1000) -> np.ndarray: 7 | assert (lhs.ndim == 1 and "lhs.ndim != 1") 8 | assert (rhs.ndim == 1 and "rhs.ndim != 1") 9 | assert (rhs.size == lhs.size and "rhs.size != lhs.size") 10 | direction = rhs - lhs 11 | direction = eps * direction / np.linalg.norm(direction) 12 | iteration = 0 13 | for iteration in range(n_iters): 14 | if np.linalg.norm(rhs - lhs) <= 2 * eps: 15 | break 16 | xc = (rhs + lhs) * 0.5 17 | if function(xc - direction) > function(xc + direction): 18 | lhs = xc 19 | else: 20 | rhs = xc 21 | print(f"\tbisect::args range : {np.linalg.norm(rhs - lhs)}") 22 | print(f"\tbisect::func probes: {iteration * 2}") 23 | return (rhs + lhs) * 0.5 24 | -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/MultidimensionalMethods/conj_gradient.py: -------------------------------------------------------------------------------- 1 | import math 2 | from typing import Callable 3 | from MultidimensionalMethods import fibonacci 4 | import numpy as np 5 | 6 | 7 | 8 | def partial(function: Callable[[np.ndarray], float], x: np.ndarray, index: int = 0, dx: float = 1e-6) -> float: 9 | x[index] -= dx 10 | fl = function(x) 11 | x[index] += 2 * dx 12 | fr = function(x) 13 | x[index] -= dx 14 | return (fr - fl) / (2 * dx) 15 | 16 | 17 | def gradient(function: Callable[[np.ndarray], float], x: np.ndarray, eps) -> np.ndarray: 18 | return np.array(tuple(partial(function, x, index, eps) for index in range(x.size))) 19 | 20 | 21 | def conj_gradient(function: Callable[[np.ndarray], float], x_start: np.ndarray, eps: float = 1e-6, 22 | n_iters: int = 1000) -> np.ndarray: 23 | assert (x_start.ndim == 1 and "x_start.ndim != 1") 24 | x_i = x_start.copy() 25 | x_i_1 = x_start.copy() 26 | grad_i = - gradient(function, x_i, eps) 27 | s_i = grad_i.copy() 28 | x_i_1 = fibonacci(function, x_i, x_i + grad_i, eps) 29 | cntr = 0 30 | for cntr in range(n_iters): 31 | grad_i_1 = gradient(function, x_i, eps) 32 | s_i_1 = grad_i_1 + s_i * math.pow(np.linalg.norm(grad_i_1), 2)/math.pow(np.linalg.norm(grad_i), 2) 33 | x_i = x_i_1.copy() 34 | x_i_1 = fibonacci(function, x_i, x_i - grad, eps) 35 | if np.linalg.norm(x_i_1 - x_i) < 2 * eps: 36 | break 37 | 38 | print(f"\tgradient descend::args range : {x_i_1}") 39 | print(f"\tgradient descend::func probes: {cntr}") 40 | 41 | return (x_i_1 + x_i) * 0.5 42 | -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/MultidimensionalMethods/fibonacci.py: -------------------------------------------------------------------------------- 1 | from typing import Callable 2 | import numpy as np 3 | 4 | 5 | def closest_fib_pair(value: float) -> tuple[float, float, int]: 6 | f_t, f_1, f_2 = 0.0, 1.0, 1.0 7 | iteration = 0 8 | while f_2 < value: 9 | iteration += 1 10 | f_t, f_1 = f_1, f_2 11 | f_2 += f_t 12 | return f_1, f_2, iteration 13 | 14 | 15 | def back_shift_fib(f_1: float, f_2: float) -> tuple[float, float]: 16 | f_t = f_2 - f_1 17 | return f_1, f_t 18 | 19 | 20 | def fibonacci(function: Callable[[np.ndarray], float], lhs: np.ndarray, rhs: np.ndarray, 21 | eps: float = 1e-6) -> np.ndarray: 22 | 23 | assert (lhs.ndim == 1 and "lhs.ndim != 1") 24 | assert (rhs.ndim == 1 and "rhs.ndim != 1") 25 | assert (rhs.size == lhs.size and "rhs.size != lhs.size") 26 | 27 | f_1, f_2, iteration = closest_fib_pair(np.linalg.norm(rhs - lhs) / eps) 28 | 29 | x_l = lhs + (f_2 - f_1) / f_2 * (rhs - lhs) 30 | x_r = lhs + f_1 / f_2 * (rhs - lhs) 31 | f_2, f_1 = back_shift_fib(f_1, f_2) 32 | fl = function(x_l) 33 | fr = function(x_r) 34 | 35 | for index in range(iteration): 36 | if fl > fr: 37 | lhs = x_l 38 | x_l = x_r 39 | fl = fr 40 | x_r = lhs + f_1 * (rhs - lhs) / f_2 41 | fr = function(x_r) 42 | else: 43 | rhs = x_r 44 | x_r = x_l 45 | fr = fl 46 | x_l = lhs + (f_2 - f_1) * (rhs - lhs)/f_2 47 | fl = function(x_l) 48 | f_2, f_1 = back_shift_fib(f_1, f_2) 49 | 50 | print(f"\tfibonacci::args range : {np.linalg.norm(rhs - lhs)}") 51 | print(f"\tfibonacci::func probes: {iteration + 2}") 52 | return (rhs + lhs) * 0.5 53 | -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/MultidimensionalMethods/golden_ratio.py: -------------------------------------------------------------------------------- 1 | from typing import Callable 2 | import numpy as np 3 | 4 | PSI = 0.6180339887498948 5 | PHI = 1.6180339887498948 6 | 7 | 8 | def golden_ratio(function: Callable[[np.ndarray], float], lhs: np.ndarray, rhs: np.ndarray, 9 | eps: float = 1e-6, n_iters: int = 1000) -> np.ndarray: 10 | 11 | assert (lhs.ndim == 1 and "lhs.ndim != 1") 12 | assert (rhs.ndim == 1 and "rhs.ndim != 1") 13 | assert (rhs.size == lhs.size and "rhs.size != lhs.size") 14 | x_l, x_r = rhs - (rhs - lhs) * PSI, lhs + (rhs - lhs) * PSI 15 | fl, fr = function(x_l), function(x_r) 16 | iteration = 0 17 | for iteration in range(n_iters): 18 | if np.linalg.norm(rhs - lhs) <= 2 * eps: 19 | break 20 | if fl > fr: 21 | lhs = x_l 22 | x_l = x_r 23 | fl = fr 24 | x_r = lhs + (rhs - lhs) * PSI 25 | fr = function(x_r) 26 | else: 27 | rhs = x_r 28 | x_r = x_l 29 | fr = fl 30 | x_l = rhs - (rhs - lhs) * PSI 31 | fl = function(x_l) 32 | 33 | print(f"\tgolden_ratio::args range : {np.linalg.norm(rhs - lhs)}") 34 | print(f"\tgolden_ratio::func probes: {iteration + 2}") 35 | return (rhs + lhs) * 0.5 36 | -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/MultidimensionalMethods/gradient_descent.py: -------------------------------------------------------------------------------- 1 | from typing import Callable 2 | from MultidimensionalMethods import fibonacci 3 | import numpy as np 4 | 5 | 6 | def partial(function: Callable[[np.ndarray], float], x: np.ndarray, index: int = 0, dx: float = 1e-6) -> float: 7 | x[index] -= dx 8 | fl = function(x) 9 | x[index] += 2 * dx 10 | fr = function(x) 11 | x[index] -= dx 12 | return (fr - fl) / (2 * dx) 13 | 14 | 15 | def gradient(function: Callable[[np.ndarray], float], x: np.ndarray, eps) -> np.ndarray: 16 | return np.array(tuple(partial(function, x, index, eps) for index in range(x.size))) 17 | 18 | 19 | def gradient_descent(function: Callable[[np.ndarray], float], x_start: np.ndarray, eps: float = 1e-6, 20 | n_iters: int = 1000) -> np.ndarray: 21 | assert (x_start.ndim == 1 and "x_start.ndim != 1") 22 | x_i = x_start.copy() 23 | x_i_1 = x_start.copy() 24 | # grad = x_start.copy() 25 | cntr = 0 26 | for cntr in range(n_iters): 27 | grad = gradient(function, x_i, eps) 28 | x_i = x_i_1.copy() 29 | x_i_1 = fibonacci(function, x_i, x_i - grad, eps) 30 | if np.linalg.norm(x_i_1 - x_i) < 2 * eps: 31 | break 32 | 33 | print(f"\tgradient descend::args range : {x_i_1}") 34 | print(f"\tgradient descend::func probes: {cntr}") 35 | 36 | return (x_i_1 + x_i) * 0.5 37 | -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/MultidimensionalMethods/penalty_function.py: -------------------------------------------------------------------------------- 1 | from typing import Callable 2 | import numpy as np 3 | 4 | 5 | class PenaltyFunction: 6 | def __init__(self, target_function: Callable[[np.ndarray], float] = None): 7 | self._target = target_function 8 | self._boundaries = set() 9 | 10 | @property 11 | def target(self) -> Callable[[np.ndarray], float]: 12 | return self._target 13 | 14 | @target.setter 15 | def target(self, value: Callable[[np.ndarray], float]) -> None: 16 | assert isinstance(value, Callable) 17 | self._target = value 18 | 19 | def add_bound(self, bound: Callable[[np.ndarray], float]) -> bool: 20 | if bound in self._boundaries or not isinstance(bound, Callable): 21 | return False 22 | self._boundaries.add(bound) 23 | return True 24 | 25 | def del_bound(self, bound: Callable[[np.ndarray], float]) -> bool: 26 | if bound in self._boundaries: 27 | return False 28 | self._boundaries.remove(bound) 29 | return True 30 | 31 | def clear_boundaries(self): 32 | self._boundaries.clear() 33 | 34 | def __call__(self, arg: np.ndarray) -> float: 35 | return (self.target(arg) if self.target else 0.0) + sum(fn(arg) for fn in self._boundaries) 36 | -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/MultidimensionalMethods/perCordDescend.py: -------------------------------------------------------------------------------- 1 | from typing import Callable 2 | from MultidimensionalMethods import fibonacci 3 | import numpy as np 4 | 5 | 6 | def perCordDescend(function: Callable[[np.ndarray], float], x_start: np.ndarray, eps: float = 1e-6, 7 | n_iters: int = 1000) -> np.ndarray: 8 | assert (x_start.ndim == 1 and "x_start.ndim != 1") 9 | x_0 = x_start.copy() 10 | x_1 = x_start.copy() 11 | step = np.ones(x_start.ndim) 12 | x_i, y_1, y_0 = np.zeros_like(x_start), np.zeros_like(x_start), np.zeros_like(x_start) 13 | opt_coord_n, coord_id = 0, 0 14 | probes = 0 15 | for i in range(n_iters): 16 | coord_id = i % x_0.size 17 | x_1[coord_id] -= eps 18 | y_0 = function(x_1) 19 | x_1[coord_id] += 2.0 * eps 20 | y_1 = function(x_1) 21 | x_1[coord_id] -= eps 22 | x_1[coord_id] += y_0 > y_1 if step else -step 23 | x_i = x_0[coord_id] 24 | x_1 = fibonacci(function, x_0, x_1, eps) 25 | x_0 = x_1.copy() 26 | if np.absolute(x_1[coord_id] - x_i) < 2 * eps: 27 | opt_coord_n += 1 28 | if opt_coord_n == x_1.size: 29 | print(f"\tperCordDescent::args range : {np.absolute(x_1[coord_id] - x_i)}") 30 | print(f"\tperCordDescent::func probes: {i}") 31 | return x_0 32 | continue 33 | opt_coord_n = 0 34 | 35 | print(f"\tperCordDescent::args range : {np.absolute(x_1[coord_id] - x_i)}") 36 | print(f"\tperCordDescent::func probes: {n_iters}") 37 | return x_0 38 | -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/OnedimensionalMethods/__init__.py: -------------------------------------------------------------------------------- 1 | from .golden_ratio import PSI, PHI, golden_ratio 2 | from .bisect import bisect 3 | from .fibonacci import fibonacci 4 | -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/OnedimensionalMethods/__pycache__/__init__.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuryStrelkov/OptimizationMethods/745af24e1c78df1e600e5f87423bf7f3d3ceaf8b/Python/OptimizationMethodsNew/OnedimensionalMethods/__pycache__/__init__.cpython-312.pyc -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/OnedimensionalMethods/__pycache__/bisect.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuryStrelkov/OptimizationMethods/745af24e1c78df1e600e5f87423bf7f3d3ceaf8b/Python/OptimizationMethodsNew/OnedimensionalMethods/__pycache__/bisect.cpython-312.pyc -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/OnedimensionalMethods/__pycache__/fibonacci.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuryStrelkov/OptimizationMethods/745af24e1c78df1e600e5f87423bf7f3d3ceaf8b/Python/OptimizationMethodsNew/OnedimensionalMethods/__pycache__/fibonacci.cpython-312.pyc -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/OnedimensionalMethods/__pycache__/golden_ratio.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuryStrelkov/OptimizationMethods/745af24e1c78df1e600e5f87423bf7f3d3ceaf8b/Python/OptimizationMethodsNew/OnedimensionalMethods/__pycache__/golden_ratio.cpython-312.pyc -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/OnedimensionalMethods/bisect.py: -------------------------------------------------------------------------------- 1 | from typing import Callable 2 | 3 | 4 | def bisect(function: Callable[[float], float], lhs: float, rhs: float, 5 | eps: float = 1e-6, n_iters: int = 1000) -> float: 6 | 7 | rhs, lhs = (lhs, rhs) if rhs < lhs else (rhs, lhs) 8 | iteration = 0 9 | for iteration in range(n_iters): 10 | if rhs - lhs <= 2 * eps: 11 | break 12 | xc = (rhs + lhs) * 0.5 13 | if function(xc - eps) > function(xc + eps): 14 | lhs = xc 15 | else: 16 | rhs = xc 17 | print(f"\tbisect::args range : {rhs - lhs}") 18 | print(f"\tbisect::func probes: {iteration * 2}") 19 | return (rhs + lhs) * 0.5 20 | -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/OnedimensionalMethods/fibonacci.py: -------------------------------------------------------------------------------- 1 | from typing import Callable 2 | 3 | 4 | def fibonacci(function: Callable[[float], float], lhs: float, rhs: float, 5 | eps: float = 1e-6) -> float: 6 | 7 | f_t, f_1, f_2 = 0.0, 1.0, 1.0 8 | rhs, lhs = (lhs, rhs) if rhs < lhs else (rhs, lhs) 9 | 10 | iteration = 0 11 | value = (rhs - lhs) / eps 12 | while f_2 < value: 13 | iteration += 1 14 | f_t, f_1 = f_1, f_2 15 | f_2 += f_t 16 | 17 | x_l = lhs + (f_2 - f_1) / f_2 * (rhs - lhs) 18 | x_r = lhs + f_1 / f_2 * (rhs - lhs) 19 | fl = function(x_l) 20 | fr = function(x_r) 21 | 22 | f_t = f_2 - f_1 23 | f_2, f_1 = f_1, f_t 24 | 25 | for index in range(iteration): 26 | if fl > fr: 27 | lhs = x_l 28 | x_l = x_r 29 | fl = fr 30 | x_r = lhs + f_1 * (rhs - lhs) / f_2 31 | fr = function(x_r) 32 | else: 33 | rhs = x_r 34 | x_r = x_l 35 | fr = fl 36 | x_l = lhs + (f_2 - f_1) * (rhs - lhs)/f_2 37 | fl = function(x_l) 38 | f_t = f_2 - f_1 39 | f_2, f_1 = f_1, f_t 40 | 41 | print(f"\tfibonacci::args range : {rhs - lhs}") 42 | print(f"\tfibonacci::func probes: {iteration + 2}") 43 | return (rhs + lhs) * 0.5 44 | -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/OnedimensionalMethods/golden_ratio.py: -------------------------------------------------------------------------------- 1 | from typing import Callable 2 | 3 | PSI = 0.6180339887498948 4 | PHI = 1.6180339887498948 5 | 6 | 7 | def golden_ratio(function: Callable[[float], float], lhs: float, rhs: float, 8 | eps: float = 1e-6, n_iters: int = 1000) -> float: 9 | 10 | rhs, lhs = (lhs, rhs) if rhs < lhs else (rhs, lhs) 11 | x_l = rhs - (rhs - lhs)*PSI 12 | x_r = lhs + (rhs - lhs)*PSI 13 | fl = function(x_l) 14 | fr = function(x_r) 15 | 16 | iteration = 0 17 | for iteration in range(n_iters): 18 | if rhs - lhs <= 2 * eps: 19 | break 20 | if fl > fr: 21 | lhs = x_l 22 | x_l = x_r 23 | fl = fr 24 | x_r = lhs + (rhs - lhs)*PSI 25 | fr = function(x_r) 26 | else: 27 | rhs = x_r 28 | x_r = x_l 29 | fr = fl 30 | x_l = rhs - (rhs - lhs)*PSI 31 | fl = function(x_l) 32 | 33 | print(f"\tgolden_ratio::args range : {rhs - lhs}") 34 | print(f"\tgolden_ratio::func probes: {iteration + 2}") 35 | return (rhs + lhs) * 0.5 36 | -------------------------------------------------------------------------------- /Python/OptimizationMethodsNew/main.py: -------------------------------------------------------------------------------- 1 | import OnedimensionalMethods 2 | import numpy as np 3 | import MultidimensionalMethods 4 | from MultidimensionalMethods import PenaltyFunction 5 | 6 | 7 | def test_f(x: float) -> float: 8 | return x*(x - 1) 9 | 10 | 11 | def test_nd(x: np.ndarray) -> float: 12 | return np.dot(x, (x - 1)) 13 | 14 | 15 | def one_dim_search_methods(): 16 | print(f'bisect result : {OnedimensionalMethods.bisect(test_f, -10.0, 10.0):>12.3f}\n') 17 | print(f'golden_ratio result: {OnedimensionalMethods.golden_ratio(test_f, -10.0, 10.0):>12.3f}\n') 18 | print(f'fibonacci result : {OnedimensionalMethods.fibonacci(test_f, -10.0, 10.0, 1.5e-6):>12.3f}') 19 | 20 | 21 | def multi_dim_search_methods(): 22 | target = PenaltyFunction() 23 | target.target = test_nd 24 | 25 | lhs = np.array((0.0, 0.0, 0.0)) 26 | rhs = np.array((1.0, 1.0, 1.0)) 27 | print(f'bisect result : {MultidimensionalMethods.bisect(target, lhs, rhs)}\n') 28 | print(f'golden_ratio result : {MultidimensionalMethods.golden_ratio(target, lhs, rhs)}\n') 29 | print(f'fibonacci result : {MultidimensionalMethods.fibonacci(target, lhs, rhs)}\n') 30 | x_start = np.array((0.0, 0.0, 0.0)) 31 | print(f'perCordDescend result : {MultidimensionalMethods.perCordDescend(target, x_start)}\n') 32 | x_start = np.array((0.0, 0.0, 0.0)) 33 | print(f'gradient_descent result : {MultidimensionalMethods.gradient_descent(target, x_start)}\n') 34 | 35 | 36 | if __name__ == "__main__": 37 | # one_dim_search_methods() 38 | multi_dim_search_methods() 39 | -------------------------------------------------------------------------------- /info.md: -------------------------------------------------------------------------------- 1 | 2 | # Лабораторные работы по методам оптимизации. 3 | ## Определения и обозначения. 4 | 1. **Промежуток неопределённости** - для методов нулевого порядка - область в которой мы ожидаем обнаружить экстремум функции. 5 | 2. **Целевая функция** - гладкая дифференциремая (до второго порядка производной) функция для которой мы ищем экстремум. 6 | 3. **Измерение целевой функции** - определение значения **целевой функции** в точке. 7 | 4. **lhs** и **rhs** - левая и правая граница **промежутка неопределённости**. 8 | 5. **eps** или **accuracy** или $$\varepsilon$$ - точность с которой мы ищем экстемум функции. 9 | 6. **Унимодальная функция** - функция с одним **глобальным** экстремумом на всей области определения. 10 | 7. **Мультимодальная функция** - функция с множеством **локальных** экстремумом на всей области определения. 11 | 8. Исследование функции **целевой функции** **f** на монотонность в окружности точки **x** радиусом **eps** - определение направления возрастания или убывания функции путём сравнения значений **f(x + eps)** и **f(x - eps)**. 12 | 9. Констатнты золотого сечения **$$\psi = 0.61803398874989484820, \phi = 1.61803398874989484820$$**. 13 | ## Требования для оформления кода реализации заданий лабораторных работ. 14 | 1. **C++** 15 | - Лаборатоные работы №1-3 написать в процедурном стиле; 16 | - Передавать целевую функцию в виде указателя или использовать **std::function<...(...)>**; 17 | - Прототипы функций писать в **".h"** файлах, а реализацию в **".cpp"**; 18 | - Каждая лабораторная работа реализуется в своей паре **".h"** и **".cpp"** файлах; 19 | - Не мешать многомерные методы с одномерными; 20 | - Функция **"main"** в отдельном файле; 21 | - Лабораторную работу №4 предпочтительно реализовать используя ООП. 22 | - Для работы с векторами и матрицами использовать набор классов из **"numerics"** или любую альтернативу на ваш выбор. 23 | 3. **Java** 24 | - Лаборатоные работы №1-3 написать в отдельных классах в виде набора статических методов; 25 | - Передавать целевую функцию в виде интерфейса и использовать **@FunctionalInterface**; 26 | - Каждая лабораторная работа реализуется в отдельном **".java"** файле; 27 | - Не мешать многомерные методы с одномерными; 28 | - Функция **"main"** в отдельном файле; 29 | - Лабораторную работу №4 предпочтительно реализовать используя ООП. 30 | - Для работы с векторами и матрицами использовать набор классов из **"mathUtils"** или любую альтернативу на ваш выбор. 31 | 5. **C#** 32 | - Лаборатоные работы №1-3 написать в отдельных статических классах в виде набора статических методов; 33 | - Передавать целевую функцию в виде делегатов, например, использовать **public delegate double Function1D(double x)**; 34 | - Каждая лабораторная работа реализуется в отдельном **".cs"** файле; 35 | - Не мешать многомерные методы с одномерными; 36 | - Функция **"Main"** в отдельном файле; 37 | - Лабораторную работу №4 предпочтительно реализовать используя ООП; 38 | - Для работы с векторами и матрицами использовать набор классов из **"MathUtils"** или любую альтернативу на ваш выбор. 39 | 7. **Python** 40 | - Каждый метод поиска из лабораторных №1-3 реализовать в отдельных **.py** модулях; 41 | - Модули лаборатоных работ №1-3 одбъединить в пакеты; 42 | - Обязательно использовать **аннотации типов Python**; 43 | - Передавать целевую функцию в виде ссылки, использовать аннотацию **function: Callable[[float],float]** или **function: Callable[[np.ndarray],float]**; 44 | - Каждая лабораторная работа реализуется в отдельном пакете, а метод в модуле; 45 | - Не мешать многомерные методы с одномерными; 46 | - Точка входа в отдельном **.py** модуле. Точка входа **```if __name__ == "__main__":...```**; 47 | - Лабораторную работу №4 предпочтительно реализовать используя ООП. 48 | 9. **Остальные языки** 49 | - Лаборатоные работы №1-3 написать в процедурном стиле; 50 | - Передавать целевую функцию в виде фагумента метода поиска; 51 | - Не мешать многомерные методы с одномерными; 52 | - Точка взода в программу в отдельном файле; 53 | - Лабораторную работу №4 предпочтительно реализовать используя ООП. 54 | 55 | ## Лабораторная работа №1. Методы одномерного поиска нулевого порядка. 56 | 1. **Дихотомия** или **метод половинного деления** - алгоритм поиска экстремума функции нулевого порядка, который предполагает поиск экстремума функции путём разделения **промежутка неопределённости** пополам и **исследования функции на монотонность** в центральной точке. Дихотомия считается самым неэффективным алгоритмом с точки зрения вычислительной сложности, так как **измерение целевой функции** осущесствляется дважды за одну итерацию. Алгоритм поиска можно свести к следующим основным шагам: 57 | - Переходим в цикл поиска, который ограничен по точности $$\varepsilon$$ и количеству итераций **maxIterations**; 58 | - Определяем центральную точку **промежутка неопределённости**: $$x_{c}=\frac{lhs+rhs}{2}$$ и рассчитываем функцию в точках $$x_{1}=x_{c}-\varepsilon$$; $$x_{2}=x_{c}+\varepsilon$$; 59 | - Если $$f\left(x_{c}-\varepsilon\right)>f\left(x_{c}+\varepsilon\right)$$ преобразуем **промежуток неопределённости** в: $$\left[x_{c}, rhs\right]$$; 60 | - Если $$f\left(x_{c}-\varepsilon\right)f\left(x_{r}\right)$$ преобразуем **промежуток неопределённости** и остальные параметры: $$\left[lhs=x_{l},rhs\right], x_{l}=x_{r}; f_{l}=f_{r}, x_{r}=lhs+\psi\left(rhs-lhs\right), f_{r}=f\left(x_{r}\right)$$; 68 | - Если $$f\left(x_{l}\right)\frac{lhs+rhs}{\varepsilon}$$, здесь $$n$$ - номер числа фибоначии/количество итераций. **Метод Фибоначчи** работает точнее, чем **золотое сечение** при одинаковом количестве **измерений функций**.чем Количество **измерений целевой функции** равно количеству итераций метода + 2. Алгоритм поиска можно свести к следующим основным шагам: 72 | - Определяем пару чисел фибоначии $$L_{n-1}, L_{n}$$ и номер числа $$n$$, где $$L_{n}>\frac{lhs+rhs}{\varepsilon}$$; 73 | - Определяем левую и правую точку разбиения отрезка: $$x_{r}=lhs+\frac{L_{n-1}}{L_{n}}\left(rhs-lhs\right))$$, $$x_{l}=lhs+\frac{L_{n}-L_{n-1}}{L_{n}}\left(rhs-lhs\right)$$; 74 | - В точках $$x_{l},x_{r}$$ делаем **измерения целевой функции**: $$f_{l}=f\left(x_{l}\right)$$, $$f_{r}=f\left(x_{r}\right)$$; 75 | - Переходим в цикл поиска, который ограничен по количеству итераций **maxIterations**; 76 | - Делаем сдвиг пары чисел фибоначчи: $$L_{n-1}, L_{n}\rightarrow L_{n-2}, L_{n-1}$$; 77 | - Если $$f\left(x_{l}\right)>f\left(x_{r}\right)$$ преобразуем **промежуток неопределённости** и остальные параметры: $$\left[lhs=x_{l}, rhs\right], x_{l}=x_{r}; f_{l}=f_{r}, x_{r}=lhs+\frac{L_{n-1}}{L_{n}}\left(rhs-lhs\right)), f_{r}=f\left(x_{r}\right)$$; 78 | - Если $$f\left(x_{l}\right)f\left(\vec{x_{c}}+\vec{dir}\right)$$ преобразуем **промежуток неопределённости** в: $$\left[\vec{x_{c}}, \vec{rhs}\right]$$; 90 | - Если $$f\left(\vec{x_{c}}-\vec{dir}\right)f\left(\vec{x_{r}}\right)$$ преобразуем **промежуток неопределённости** и остальные параметры: $$\left[\vec{lhs}=\vec{x_{l}},\vec{rhs}\right], \vec{x_{l}}=\vec{x_{r}}; \vec{f_{l}}=\vec{f_{r}}, \vec{x_{r}}=\vec{lhs}+\psi\left(\vec{rhs}-\vec{lhs}\right), f_{r}=f\left(\vec{x_{r}}\right)$$; 98 | - Если $$f\left(\vec{x_{l}}\right)\frac{|\vec{rhs} - \vec{lhs}|}{\varepsilon}$$, здесь $$n$$ - номер числа фибоначии/количество итераций. **Метод Фибоначчи** работает точнее, чем **золотое сечение** при одинаковом количестве **измерений функций**.чем Количество **измерений целевой функции** равно количеству итераций метода + 2. Алгоритм поиска можно свести к следующим основным шагам: 102 | - Определяем пару чисел фибоначии $$L_{n-1}, L_{n}$$ и номер числа $$n$$, где $$L_{n}>\frac{|\vec{rhs}-\vec{lhs}|}{\varepsilon}$$; 103 | - Определяем левую и правую точку разбиения отрезка: $$x_{r}=\vec{lhs}+\frac{L_{n-1}}{L_{n}}\left(\vec{rhs} - \vec{lhs}\right))$$, $$x_{l}=\vec{lhs}+\frac{L_{n}-L_{n-1}}{L_{n}}\left(\vec{rhs} - \vec{lhs}\right)$$; 104 | - В точках $$\vec{x_{l}},\vec{x_{r}}$$ делаем **измерения целевой функции**: $$f_{l}=f\left(\vec{x_{l}}\right)$$, $$f_{r}=f\left(\vec{x_{r}}\right)$$; 105 | - Переходим в цикл поиска, который ограничен по количеству итераций **maxIterations**; 106 | - Делаем сдвиг пары чисел фибоначчи: $$L_{n-1}, L_{n}\rightarrow L_{n-2}, L_{n-1}$$; 107 | - Если $$f\left(\vec{x_{l}}\right)>f\left(\vec{x_{r}}\right)$$ преобразуем **промежуток неопределённости** и остальные параметры: $$\left[\vec{lhs}=\vec{x_{l}}, \vec{rhs}\right], \vec{x_{l}}=\vec{x_{r}}; f_{l}=f_{r}, \vec{x_{r}}=\vec{lhs}+\frac{L_{n-1}}{L_{n}}\left(\vec{rhs} - \vec{lhs}\right)), f_{r}=f\left(\vec{x_{r}}\right)$$; 108 | - Если $$f\left(\vec{x_{l}}\right)