Esempio n. 1
0
 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;
 }
Esempio n. 2
0
        /// <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);
        }