public BooleanEnumPlan(BooleanEnumPlan element) { Vector = new BooleanVector(element.Vector); Indeces = new Vector <int>(element.Indeces); ArgBound = new Vector <double>(element.ArgBound); FuncMin = element.FuncMin; FuncMax = element.FuncMax; }
/// <summary> /// Решение задачи линейного программирования /// </summary> /// <param name="minimax"></param> /// <param name="optimalVectors"></param> /// <param name="optimalValues"></param> /// <param name="trace"></param> /// <returns></returns> public bool Execute(ILinearMiniMax <T> minimax, ref IEnumerable <Vector <T> > optimalVectors, ref IEnumerable <T> optimalValues, ITrace trace) { // Реализуем алгоритм только для случая наращивания базиса по одной переменной Debug.Assert(H == 1); Debug.Assert(minimax.A.Rows == minimax.R.Count()); Debug.Assert(minimax.A.Rows == minimax.B.Count()); Debug.Assert(minimax.A.Columns == minimax.C.Count()); AppendLineCallback appendLineCallback = trace != null ? trace.AppendLineCallback : null; ProgressCallback progressCallback = trace != null ? trace.ProgressCallback : null; CompliteCallback compliteCallback = trace != null ? trace.CompliteCallback : null; if (progressCallback != null) { progressCallback(0, minimax.C.Count); } // Количество переменных int n = minimax.C.Count; // Величине рекорда присваивается заведомо плохое решение double r = minimax.Target == Target.Maximum ? Double.MinValue : Double.MaxValue; BooleanEnumPlan optimal = null; // Исходным выбранным частичным планом считается тот, базис которого пуст for ( var stack = new StackListQueue <BooleanEnumPlan>( new BooleanEnumPlan( new BooleanVector(), new Vector <int>(), minimax)); stack.Any(); ) { BooleanEnumPlan element = stack.Pop(); Debug.WriteLine("element = {0}", element); // Генерируем все возможные соседние планы, связанные с введением в базис H переменных // и вычисляем их оценки if (appendLineCallback != null) { appendLineCallback( string.Format( "Генерируем все возможные соседние планы, связанные с введением в базис {0} переменных", H)); } Debug.WriteLine( "Генерируем все возможные соседние планы, связанные с введением в базис {0} переменных", H); var list = new StackListQueue <BooleanEnumPlan>(new[] { true, false }.Select(value => new BooleanEnumPlan(new BooleanVector(element.Vector) { value }, new Vector <int>(element.Indeces) { Enumerable.Range(0, n).Except(element.Indeces).First() }, minimax)) .Where(item => item.ArgBound.All(x => x >= 0.0))); stack.Push(list); if (appendLineCallback != null) { appendLineCallback(string.Format("Количество подмножеств = {0}", stack.Count)); } Debug.WriteLine("Количество подмножеств = {0}", stack.Count); for (; stack.Any();) { // На множестве планов выбрать планы с наибольшим числом введёных переменных // На выбраном множестве выбрать с наилучшей оценкой if (appendLineCallback != null) { appendLineCallback( "На множестве планов выбрать планы с наибольшим числом введёных переменных"); } if (appendLineCallback != null) { appendLineCallback("На выбраном множестве выбрать с наилучшей оценкой"); } Debug.WriteLine("На множестве планов выбрать планы с наибольшим числом введёных переменных"); Debug.WriteLine("На выбраном множестве выбрать с наилучшей оценкой"); int max1 = stack.Max(item => item.Indeces.Count); list = new StackListQueue <BooleanEnumPlan>(stack.Where(item => item.Indeces.Count == max1)); double maxMax = list.Max(item => item.FuncMax); double minMin = list.Min(item => item.FuncMin); element = minimax.Target == Target.Maximum ? list.First(item => item.FuncMax == maxMax) : list.First(item => item.FuncMin == minMin); stack.Remove(element); Debug.WriteLine("element = {0}", element); if (minimax.Target == Target.Maximum && r <= maxMax || minimax.Target == Target.Minimum && r >= minMin) { // Если оценка элемента лучше рекорда if (appendLineCallback != null) { appendLineCallback("Оценка элемента лучше рекорда"); } if (element.Indeces.Count == n) { // Если в базис введены все элементы if (appendLineCallback != null) { appendLineCallback("В базис введены все элементы"); } // Запоминаем в рекорд оценку (т.е. значение для этого вектора) // и запоминаем этот план if (appendLineCallback != null) { appendLineCallback("Запоминаем в рекорд оценку"); } r = minimax.Target == Target.Maximum ? element.FuncMax : element.FuncMin; optimal = new BooleanEnumPlan(element); } else { // Иначе переходим к генерации соседних планов stack.Push(element); break; } } // Выводим из базиса H последних переменных, отбросив остальные планы с таким же числом переменных if (appendLineCallback != null) { appendLineCallback( string.Format( "Выводим из базиса {0} последних переменных, отбросив остальные планы с таким же числом переменных", H)); } element = new BooleanEnumPlan( new BooleanVector(element.Vector.GetRange(0, element.Vector.Count - 1)), new Vector <int>(element.Indeces.GetRange(0, element.Indeces.Count - 1)), minimax); stack.RemoveAll(item => item.Indeces.Count == element.Indeces.Count); Debug.WriteLine("element = {0}", element); if (appendLineCallback != null) { appendLineCallback(string.Format("Количество подмножеств = {0}", stack.Count)); } Debug.WriteLine("Количество подмножеств = {0}", stack.Count); if (element.Indeces.Count == 0) { break; } } } // Завершаем алгоритм и возвращаем найденное решение if (optimal == null) { return(false); } optimalVectors = new StackListQueue <Vector <T> >( new Vector <T>(optimal.Indeces.Select(index => optimal.Vector[index] ? (T)(dynamic)1 : default(T)))); optimalValues = new StackListQueue <T>((T)(dynamic)r); if (compliteCallback != null) { compliteCallback(); } return(true); }