/// <summary> /// Конструктор по умолчанию. /// </summary> public IndexMethodInternal() { Left = new double[Trial.MaxNumberOfDimensions]; Right = new double[Trial.MaxNumberOfDimensions]; Point = new double[Trial.MaxNumberOfDimensions]; Functions = new List <OptimLab.FunctionDelegate>(); Trials = new SortedList <double, Trial>(); Iv = new List <List <Trial> >(); BestTrial = new Trial(); BestTrial.Index = Trial.MaxNumberOfFunctions; BestTrial.CalculatedValues = new double[Trial.MaxNumberOfFunctions]; for (int i = 0; i < Trial.MaxNumberOfFunctions; i++) { BestTrial.CalculatedValues[i] = Double.MaxValue; } }
/// <summary> /// Конструктор копирования. /// </summary> /// <param name="trial">Испытание-образец.</param> public Trial(Trial trial) { Core = trial.Core; X = trial.X; Index = trial.Index; R = trial.R; DeltaX = trial.DeltaX; Point = new double[trial.Point.Length]; for (int i = 0; i < trial.Point.Length; i++) { Point[i] = trial.Point[i]; } CalculatedValues = new double[trial.CalculatedValues.Length]; for (int i = 0; i < trial.CalculatedValues.Length; i++) { CalculatedValues[i] = trial.CalculatedValues[i]; } }
/// <summary> /// Проведение итерации алгоритма. /// </summary> public void MakeIteration() { if (!Stop) { NumberOfTrials++; RecalculateRs(); // Вычисление максимальной характеристики. double max = Double.MinValue; double value; int interval = 0; for (int i = 1; i < Trials.Count; i++) { value = Trials.Values[i].R; if (value > max) { max = value; interval = i; } } // Проведение испытания в интервале с максимальной характеристикой. Trial t = Trials.Values[interval]; Trial t1 = Trials.Values[interval - 1]; if ((t.Index != t1.Index) || ((t.Index == t1.Index) && (t.Index == -1))) { MakeNewTrial((t.X + t1.X) / 2.0); } else { MakeNewTrial((t.X + t1.X) / 2.0 - (((t.CalculatedValues[t.Index] - t1.CalculatedValues[t1.Index]) > 0) ? 1 : -1) * Math.Pow(Math.Abs(t.CalculatedValues[t.Index] - t1.CalculatedValues[t1.Index]) / Mv[t.Index], Dimension) / 2.0 / Rv); } } }
/// <summary> /// Проведение испытания. /// </summary> /// <param name="x">Прообраз.</param> private void MakeNewTrial(double x) { Trial trial = new Trial(); trial.Point = new double[Dimension]; trial.CalculatedValues = new double[Trial.MaxNumberOfFunctions]; for (int i = 0; i < Functions.Count; i++) { trial.CalculatedValues[i] = Double.MaxValue; } // Прообраз на отрезке [0, L]. trial.X = x; // Номер ядра, проводившего испытание. trial.Core = (int)Math.Floor(x); // Вычисление образа в стандартном гиперкубе. if (L == 1) { Point = OptimLab.PeanoMap.CalculateImage(x, Dimension, Density); } else { Point = OptimLab.PeanoMap.CalculateImageMultiMap(x, Dimension, Density); } // Вычисление всех прообразов. double[] xp = new double[L]; int kp = 1; xp[0] = trial.X; double funcvalue; if (L == 1) { // Линейное преобразование - перевод координат из единичного гиперкуба на реальный. for (int i = 0; i < Dimension; i++) { Point[i] = Left[i] + (Right[i] - Left[i]) * (Point[i] + 0.5); } for (int i = 0; i < Functions.Count; i++) { NumberOfEvaluations[i]++; funcvalue = Functions[i](Point); trial.CalculatedValues[i] = funcvalue; if (i == Functions.Count - 1) { trial.Index = Functions.Count - 1; break; } if (funcvalue > 0.0) { trial.Index = i; break; } } } // Проверка "разверточного" (нулевого) ограничения. if (L > 1) { funcvalue = g0(Point); trial.CalculatedValues[0] = funcvalue; NumberOfEvaluations[0]++; if (funcvalue > 0.0) { trial.Index = 0; trial.CalculatedValues[0] = funcvalue; // Линейное преобразование - перевод координат из единичного гиперкуба на реальный. for (int i = 0; i < Dimension; i++) { Point[i] = Left[i] + (Right[i] - Left[i]) * (Point[i] + 0.5); } } else { xp = OptimLab.PeanoMap.CalculateAllPreimages(Point, Dimension, Density, L - 1); kp = L; // Линейное преобразование - перевод координат из единичного гиперкуба на реальный. for (int i = 0; i < Dimension; i++) { Point[i] = Left[i] + (Right[i] - Left[i]) * (Point[i] + 0.5); } for (int i = 1; i < Functions.Count; i++) { NumberOfEvaluations[i]++; funcvalue = Functions[i](Point); trial.CalculatedValues[i] = funcvalue; if (i == Functions.Count - 1) { trial.Index = Functions.Count - 1; break; } if (funcvalue > 0.0) { trial.Index = i; break; } } } } for (int d = 0; d < Dimension; d++) { trial.Point[d] = Point[d]; } if (trial.Index > MaxIndex) { MaxIndex = trial.Index; } // Вставка прообразов. if (Trials.Count <= L) { trial.DeltaX = 1.0; trial.Index = -1; Trials.Add(trial.X, trial); PreimageIndex = trial.Index; } else { for (int i = 0; i < kp; i++) { Trial ins = new Trial(trial); ins.X = xp[i]; if (Trials.ContainsKey(ins.X)) { Stop = true; } else { Trials.Add(ins.X, ins); } Trial j = Trials.Values[Trials.IndexOfKey(ins.X) + 1]; Trial j1 = Trials.Values[Trials.IndexOfKey(ins.X) - 1]; if (j.X - j1.X < CurrentEpsilon) { CurrentEpsilon = j.X - j1.X; } CalculateDeltaX(ins.X); CalculateDeltaX(j.X); CalculateMv(ins.X); PreimageIndex = ins.Index; } } // Оценка значений. if ((trial.Index == MaxIndex) && (trial.CalculatedValues[trial.Index] < BestTrial.CalculatedValues[trial.Index])) { BestTrial = trial; BestTrial.Index = Functions.Count - 1; } }
/// <summary> /// Заполнение множества Mv. /// </summary> /// <param name="x">Прообраз.</param> private void CalculateMv(double x) { Trial p = Trials[x]; double deltax = 0.0; int tek_index = p.Index; if ((L > 1) && (tek_index == 0)) { Mv[0] = 2.0 * Math.Sqrt(Dimension + 3.0); return; } Trial i; double rpr = 0.0; if (Trials.IndexOfKey(p.X) != 0) { deltax += p.DeltaX; i = Trials.Values[Trials.IndexOfKey(x) - 1]; while (Trials.IndexOfKey(i.X) != 0) { if (i.CalculatedValues[tek_index] < Double.MaxValue) { break; } deltax += i.DeltaX; i = Trials.Values[Trials.IndexOfKey(i.X) - 1]; } if (((Trials.IndexOfKey(i.X) != 0) || ((Trials.IndexOfKey(i.X) == 0) && (p.Index == i.Index))) && ((L == 1) || ((L > 1) && ((int)p.X == (int)i.X)))) { rpr = Math.Abs(i.CalculatedValues[tek_index] - p.CalculatedValues[tek_index]) / deltax; if ((rpr > Mv[tek_index]) || ((Mv[tek_index] == 1.0) && (rpr > 0.0))) { Mv[tek_index] = rpr; } } } deltax = 0.0; i = Trials.Values[Trials.IndexOfKey(x) + 1]; while (Trials.IndexOfKey(i.X) != Trials.Count - 1) { deltax += i.DeltaX; if (i.CalculatedValues[tek_index] < Double.MaxValue) { break; } i = Trials.Values[Trials.IndexOfKey(i.X) + 1]; } if ((Trials.IndexOfKey(i.X) != Trials.Count - 1) && ((L == 1) || ((L > 1) && (p.Index == i.Index)))) { rpr = Math.Abs(i.CalculatedValues[tek_index] - p.CalculatedValues[tek_index]) / deltax; if ((rpr > Mv[tek_index]) || ((Mv[tek_index] == 1.0) && (rpr > 0.0))) { Mv[tek_index] = rpr; } } }