Пример #1
0
        public List <double[]> FormScheduleByVectors(double[] targets, List <double[]> fixValues = null)
        {
            if (fixValues == null)
            {
                fixValues = AlgorithmHelper.CreateListOfArrays(_period, _dimension, -1.0);
            }

            if (targets == null || fixValues == null || fixValues.Count() != _period || fixValues.Any(x => x == null))
            {
                throw new ArgumentNullException();
            }
            if (fixValues.Any(x => x.Count() != targets.Count()))
            {
                throw new ArgumentException();
            }

            double[] normTargets = targets.Zip(_maxFlows, (x, y) => x / y).ToArray();

            List <double[]> decompositions = _normRegimesCombinations.Select(x => GetDimensionDecomposition(normTargets, x, _period)).ToList();
            List <double[]> test           = decompositions.Select((x, i) =>
            {
                if (x == null)
                {
                    return(null);
                }
                var vol = _regimesCombinations[i].Zip(x, (comb, decomp) => comb.Select(c => c * decomp).ToArray()).ToList();
                return(AlgorithmHelper.GetSumOnInterval(vol, 0, vol.Count()));
            }).ToList();

            return(null);
        }
Пример #2
0
        //public List<double[]> GetGridPoints(int[] stepsCount)
        //{
        //    if (_realDimension == 0)
        //        return new List<double[]> { _basePoints[0] };

        //    List<double[]> grid;
        //    int[] realStepsCount = AlgorithmHelper.GetArrayByMask(stepsCount, _notEqMask);
        //    if (_realDimension == 1)
        //        grid = GetSingleDimensionGrid(realStepsCount);
        //    else
        //        grid = GetMultiDimensionGrid(realStepsCount);

        //    if (_realDimension != Dimension)
        //    {
        //        grid = grid.Select(realPoint => ConvertFromReal(realPoint)).ToList();
        //    }

        //    return grid;
        //}

        public bool IsPointInConvexHull(double[] point)
        {
            if (point.Count() != Dimension)
            {
                throw new Exception();
            }

            if (_realDimension == 0)
            {
                return(point.SequenceEqual(_max));
            }

            if (_realDimension != Dimension)
            {
                for (int i = 0; i < Dimension; i++)
                {
                    if (!_notEqMask[i] && point[i] != _max[i])
                    {
                        return(false);
                    }
                }
            }

            if (_realDimension == 1)
            {
                int idx = _notEqMask.IndexOf(true);
                return(point[idx] <= _max[idx] && point[idx] >= _min[idx]);
            }

            return(IsRealPointInConvexHull(AlgorithmHelper.GetArrayByMask(point, _notEqMask)));
        }
Пример #3
0
        public ConvexHull(List <double[]> basePoints)
        {
            int dimension = basePoints[0].Count();

            if (dimension == 0)
            {
                throw new ArgumentException();
            }
            if (basePoints.Any(x => x.Count() != dimension))
            {
                throw new ArgumentException();
            }

            Dimension      = dimension;
            _basePoints    = AlgorithmHelper.RemoveDuplicates(basePoints);
            _max           = AlgorithmHelper.GetMaxInListByComponents(_basePoints);
            _min           = AlgorithmHelper.GetMinInListByComponents(_basePoints);
            _notEqMask     = _max.Zip(_min, (x, y) => x != y).ToArray();
            _realDimension = _notEqMask.Count(x => x);

            if (_realDimension > 0)
            {
                _realPoints = AlgorithmHelper.RemoveDuplicates(AlgorithmHelper.MaskListOfArrays(_basePoints, _notEqMask));
                _realMax    = AlgorithmHelper.GetArrayByMask(_max, _notEqMask);
                _realMin    = AlgorithmHelper.GetArrayByMask(_min, _notEqMask);

                if (_realDimension > 1)
                {
                    _convexHull = MIConvexHull.ConvexHull.Create(_realPoints);
                }
            }

            CalculateInequalities();
        }
        private static List<double[]> DecreaseRegime(ISection section, List<double[]> schedule, double volume, List<int> indexes, bool allowZero, bool input = true)
        {
            List<double[]> newSchedule = AlgorithmHelper.GetIndexes(schedule, indexes);
            double newVolume = newSchedule.Sum(x => input ? x.First() : x.Last());
            double oldSectionVolume = newVolume;
            int len = indexes.Count();
            while (true)
            {
                int zeroCounter = 0;
                bool end = false;
                for (int i = 0; i < len; i++)
                {
                    var idx = indexes[i];
                    var lowerRegime = section.GetLowerRegime(idx, newSchedule[i], !input);
                    if (lowerRegime != null)
                    {
                        if (input)
                            newVolume -= newSchedule[i].First() - lowerRegime.First();
                        else
                            newVolume -= newSchedule[i].Last() - lowerRegime.Last();

                        if (oldSectionVolume - newVolume > volume || newVolume < 0)
                        {
                            end = true;
                            break;
                        }
                        newSchedule[i] = lowerRegime;
                    }
                    else
                    {
                        zeroCounter++;
                    }
                }

                if (end)
                    break;

                if (zeroCounter == len)
                {
                    if (allowZero)
                        for (int i = len - 1; i >= 0; i--)
                        {
                            if (input)
                                newVolume -= newSchedule[i].First();
                            else
                                newVolume -= newSchedule[i].Last();

                            if (oldSectionVolume - newVolume > volume || newVolume < 0)
                                break;

                            newSchedule[i] = new double[section.Dimension];
                        }
                    break;
                }
            }

            return newSchedule;
        }
Пример #5
0
        public List <double[]> GetSchedule(double[] targets, List <double[]> fixValues = null)
        {
            if (fixValues == null)
            {
                fixValues = AlgorithmHelper.CreateListOfArrays(Period, Dimension, -1.0);
            }

            return(FormSchedule(targets, targets.Select(x => 1.0).ToArray(), fixValues));
        }
Пример #6
0
        public double[] FindNearestInteriorPoint(double[] point, bool[] notUpper, double[] weights = null)
        {
            if (weights == null)
            {
                weights = _max.Select(x => 1.0).ToArray();
            }

            if (point.Count() != Dimension)
            {
                throw new Exception();
            }

            if (_realDimension == 0)
            {
                return(_max);
            }

            var nearestPoint = point.Select(x => x).ToArray();

            if (_realDimension != Dimension)
            {
                for (int i = 0; i < Dimension; i++)
                {
                    if (!_notEqMask[i])
                    {
                        nearestPoint[i] = _max[i];
                    }
                }
            }


            if (_realDimension == 1)
            {
                int idx = _notEqMask.IndexOf(true);
                if (nearestPoint[idx] < _min[idx])
                {
                    if (notUpper[idx])
                    {
                        return(null);
                    }
                    else
                    {
                        nearestPoint[idx] = _min[idx];
                    }
                }
                else if (nearestPoint[idx] > _max[idx])
                {
                    nearestPoint[idx] = _max[idx];
                }

                return(nearestPoint);
            }

            var nearestRealPoint = NearestRealPoint(AlgorithmHelper.GetArrayByMask(nearestPoint, _notEqMask), AlgorithmHelper.GetArrayByMask(weights, _notEqMask), AlgorithmHelper.GetArrayByMask(notUpper, _notEqMask));

            return(ConvertFromReal(nearestRealPoint));
        }
Пример #7
0
        public FakeTechnologicalSectionAlgorithm(List <double[]> schedule)
        {
            _schedule    = schedule;
            _regimes     = AlgorithmHelper.RemoveDuplicates(_schedule);
            _normRegimes = AlgorithmHelper.NormalizeByComponents(_regimes);

            Period    = schedule.Count();
            Dimension = schedule[0].Count();
        }
Пример #8
0
        public List <double[]> FormScheduleContinuousRegimeField(double[] targets, List <double[]> fixValues = null, int neededPoint = -1)
        {
            if (fixValues == null)
            {
                fixValues = AlgorithmHelper.CreateListOfArrays(_period, _dimension, -1.0);
            }

            List <double[]> result = AlgorithmHelper.CombineIntoList(_algorithms.Select((x, i) => x.FormScheduleContinuousRegimeField(targets[i], fixValues.Select(y => y[i]).ToList(), neededPoint)).ToArray());

            return(result);
        }
Пример #9
0
        /// <summary>
        /// Получает точку на границе выпуклой оболочки, ближайшую к заданной точке, решая задачу квадратичного программирования
        /// </summary>
        /// <param name="realPoint">Точка, не принадлежащая к выпуклой оболочке</param>
        /// <returns></returns>
        private double[] NearestRealPoint(double[] realPoint, double[] weights, bool[] notUpper)
        {
            var faces  = _convexHull.Faces.ToList();
            int fCount = faces.Count();

            // Получаем свободный член уравнений поверхностей
            double[] facesD = faces.Select(face =>
            {
                return(face.Normal.Zip(face.Vertices[0].Position, (x, y) => x * y).Sum());
            }).ToArray();

            double[,] Q = new double[_realDimension, _realDimension];
            double[] d = new double[_realDimension];
            for (int i = 0; i < _realDimension; i++)
            {
                Q[i, i] = weights[i] * weights[i] * 2.0;
                d[i]    = weights[i] * weights[i] * (-2.0 * realPoint[i]);
            }

            bool hasUpperBound = notUpper.Any(x => x);
            int  constrCount   = hasUpperBound ? fCount + _realDimension : fCount;

            double[,] A = new double[constrCount, _realDimension];
            double[] b = new double[constrCount];
            for (int i = 0; i < fCount; i++)
            {
                b[i] = -facesD[i];
                for (int j = 0; j < _realDimension; j++)
                {
                    A[i, j] = -faces[i].Normal[j];
                }
            }
            if (hasUpperBound)
            {
                for (int i = fCount; i < fCount + _realDimension; i++)
                {
                    int dim = i - fCount;
                    b[i]      = notUpper[dim] ? -realPoint[dim] : -_realMax[dim] * 0.1;
                    A[i, dim] = -1.0;
                }
            }

            return(AlgorithmHelper.SolveQP(Q, d, A, b, 0));
        }
            public void Check(TwoPipeAlgorithm algo)
            {
                if (inTarget < 0 || outTarget < 0)
                {
                    throw new ArgumentException();
                }
                if (minLevel >= maxLevel || minLevel >= algo._bufferVolume || maxLevel <= 0 || startLevel > maxLevel || startLevel < minLevel)
                {
                    throw new ArgumentException();
                }

                if (minLevel < 0)
                {
                    minLevel = 0;
                }
                if (maxLevel > algo._bufferVolume)
                {
                    maxLevel = algo._bufferVolume;
                }

                if (pumpsSchedule == null)
                {
                    pumpsSchedule = AlgorithmHelper.CreateListOfElements(algo._period, 0.0);
                }
                if (inFixValues == null)
                {
                    inFixValues = AlgorithmHelper.CreateListOfElements(algo._period, -1.0);
                }
                if (outFixValues == null)
                {
                    outFixValues = AlgorithmHelper.CreateListOfElements(algo._period, -1.0);
                }

                if (pumpsSchedule.Count() != algo._period || inFixValues.Count() != algo._period || outFixValues.Count() != algo._period)
                {
                    throw new ArgumentException();
                }
            }
        public TwoPipeAlgorithm(List <double> regimesIn, List <double> maxFlowIn, List <double> regimesOut, List <double> maxFlowOut, double bufferVolume)
        {
            _regimesIn = regimesIn ?? throw new ArgumentNullException();
            _regimesIn.Sort();
            _maxFlowIn = maxFlowIn ?? throw new ArgumentNullException();

            _period      = maxFlowIn.Count();
            _maxVolumeIn = _maxFlowIn.Sum(x => _regimesIn.Last(y => y <= x));

            _regimesOut = regimesOut ?? throw new ArgumentNullException();
            _regimesOut.Sort();
            _maxFlowOut   = maxFlowOut ?? throw new ArgumentNullException();
            _maxVolumeOut = _maxFlowOut.Sum(x => _regimesOut.Last(y => y <= x));

            _bufferVolume = bufferVolume;

            _regimeCombinations = AlgorithmHelper.CartesianProduct(new List <List <double> >()
            {
                _regimesIn, _regimesOut
            }).Select(x => new RegimeCombination(x.First(), x.Last())).ToList();

            _avaliableRegimeCombinations = _maxFlowIn.Zip(_maxFlowOut, (mf1, mf2) => _regimeCombinations.Where(r => r.InVolume <= mf1 && r.OutVolume <= mf2).ToList()).ToList();

            _differences = new List <Tuple <RegimeCombination, RegimeCombination, double> >();

            foreach (var r1 in _regimeCombinations)
            {
                foreach (var r2 in _regimeCombinations)
                {
                    _differences.Add(new Tuple <RegimeCombination, RegimeCombination, double>(r1, r2,
                                                                                              (Math.Abs(r1.InVolume - r2.InVolume) / _regimesIn.Max() + Math.Abs(r1.OutVolume - r2.OutVolume) / _regimesOut.Max()) / 2));
                }
            }

            _inAlgo  = new SinglePipeAlgorithm(_regimesIn, _maxFlowIn);
            _outAlgo = new SinglePipeAlgorithm(_regimesOut, _maxFlowOut);
        }
        public double[] GetNearestPumpsPoit(double[] Gpumps, RepairMathModel repair, double[] pumpsPriority = null)
        {
            CheckRepair(repair);
            CheckPumps(Gpumps);
            if (pumpsPriority == null)
            {
                pumpsPriority = pumpSign.Select(x => 1.0).ToArray();
            }
            else
            {
                if (pumpsPriority.Count() != PumpsCount)
                {
                    throw new Exception();
                }
                if (pumpsPriority.Any(x => x < 0))
                {
                    throw new Exception();
                }
            }

            var system = GetSystemOfInequalities(repair);

            double[,] A = system.Item1.ToMatrix().Multiply(-1.0);
            double[] b = system.Item2.Multiply(-1.0);

            double[,] Q = new double[PumpsCount, PumpsCount];
            double[] d = new double[PumpsCount];

            for (int i = 0; i < PumpsCount; i++)
            {
                Q[i, i] = 2.0 * pumpsPriority[i] * pumpsPriority[i];
                d[i]    = pumpsPriority[i] * pumpsPriority[i] * -2.0 * Gpumps[i];
            }

            return(AlgorithmHelper.SolveQP(Q, d, A, b, 0));
        }
Пример #13
0
        public List <double[]> FormSchedule(double[] targets, double[] weights, List <double[]> fixValues = null)
        {
            if (targets == null || weights == null)
            {
                throw new ArgumentNullException();
            }

            // Понижаем объемы по трубе до максимально возможных
            targets = targets.Zip(_maxVolumes, (x, y) => x > y ? y : x).ToArray();

            if (fixValues == null)
            {
                fixValues = AlgorithmHelper.CreateListOfArrays(_period, _dimension, -1.0);
            }

            List <double[]> notSortedSchedule = fixValues.Select(x => x.Select(y => y).ToArray()).ToList();

            for (int i = 0; i < _dimension; i++)
            {
                targets[i] -= fixValues.Sum(x => x[i] < 0 ? 0 : x[i]);
            }
            targets = targets.Select(x => x < 0 ? 0 : x).ToArray();

            //////////////////////////////////////////////////////////////////////////////////////////////////////////
            // Получаем режимы, которыми доступно перекачать данный объем
            //////////////////////////////////////////////////////////////////////////////////////////////////////////

            // Не запланированные объемы перекачки
            double[] currentTarget = targets.Select(x => x).ToArray();
            // Не запланированное время
            int currentPeriod = _period - notSortedSchedule.Count(x => x[0] > 0);

            // Начинаем заполнять интервалы
            for (int idx = 0; idx < _period; idx++)
            {
                if (notSortedSchedule[idx][0] >= 0)
                {
                    continue;
                }

                // Выберем доступные режимы
                List <double[]> strongConstrains = new List <double[]>(),
                                softConstrains   = new List <double[]>();
                bool strong,
                     soft;
                double[] rgm;
                for (int i = 0; i < _avaliableNormRegimesOnIntervals[idx].Count(); i++)
                {
                    soft   = true;
                    strong = true;
                    rgm    = _avaliableNormRegimesOnIntervals[idx][i];
                    for (int j = 0; j < _dimension; j++)
                    {
                        // Если нельзя качать по трубе, а качаем, то режим не подходит
                        if (currentTarget[j] < _minFlows[j] && rgm[j] > 0 && _constraints[j])
                        {
                            soft = false;
                            break;
                        }

                        // Если нужно качать по трубе, но не качаем, то режим не подходит
                        if (strong && currentTarget[j] > _minFlows[j] && rgm[j] == 0)
                        {
                            strong = false;
                        }
                    }

                    if (soft)
                    {
                        softConstrains.Add(rgm);

                        if (strong)
                        {
                            strongConstrains.Add(rgm);
                        }
                    }
                }

                // Выбираем доступные для интервала режимы
                List <double[]> currentAvaliableRegimes = strongConstrains.Count() == 0 ? softConstrains : strongConstrains;

                // Нормированный режим для текущего объема перекачки
                //double[] normTargetRegime = currentTarget.Zip(_maxFlows, (x,y) => x / (currentPeriod * y)).ToArray();
                double[] targetRegime = FormScheduleContinuousRegimeField(targets, notSortedSchedule, idx)[0].Zip(_maxFlows, (x, y) => x / y).ToArray();

                // Ищем ближайший к нему режим среди доступных
                double[] bestRegime = currentAvaliableRegimes[AlgorithmHelper.NearestByDistance(currentAvaliableRegimes, targetRegime)];

                notSortedSchedule[idx] = _regimes[_normRegimes.IndexOf(bestRegime)];

                // Уменьшаем цель
                currentTarget = currentTarget.Zip(notSortedSchedule[idx], (x, y) => x - y).ToArray();

                // Уменьшаем время
                currentPeriod--;
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////////
            // Расставим полученные режимы (только те, которые не фиксированы)
            //////////////////////////////////////////////////////////////////////////////////////////////////////////

            // Сгруппируем режимы, получим количество каждого режима
            var grouped = notSortedSchedule
                          .Where((x, i) => fixValues[i][0] < 0)
                          .GroupBy(x => x).ToDictionary(x => x.Key, x => x.Count());
            // Получим доступные на интервалах режимы
            List <List <double[]> > avaliableRegimes = _avaliableRegimesOnIntervals.Select(x => x.Where(y => grouped.ContainsKey(y)).ToList()).ToList();

            // Пока просто отсортируем режимы в пределах интервалов с одинаковыми возможными режимами

            // Сгруппируем индексы по списку доступных режимов
            Dictionary <List <double[]>, List <int> > indexesOfSameRegimes = new Dictionary <List <double[]>, List <int> >();

            for (int i = 0; i < _period; i++)
            {
                if (fixValues[i][0] >= 0)
                {
                    continue;
                }

                List <double[]> cur = avaliableRegimes[i];
                List <double[]> key = null;
                foreach (var el in indexesOfSameRegimes)
                {
                    if (AlgorithmHelper.ListsEqualityNoOrder(cur, el.Key))
                    {
                        key = el.Key;
                        break;
                    }
                }
                if (key == null)
                {
                    indexesOfSameRegimes.Add(cur, new List <int>());
                    key = cur;
                }

                indexesOfSameRegimes[key].Add(i);
            }

            // Сортируем в пределах возможных интервалов (по дистанции между режимами и координатой (0,...,0) )

            List <double[]> sortedSchedule = fixValues.Select(x => x.Select(y => y).ToArray()).ToList();

            foreach (var el in indexesOfSameRegimes)
            {
                List <double[]> forSort = el.Value.Select((x) => _normRegimes[_regimes.IndexOf(notSortedSchedule[x])]).ToList();
                forSort.Sort((x, y) =>
                {
                    double dx = AlgorithmHelper.GetLength(x), dy = AlgorithmHelper.GetLength(y);

                    if (dx == dy)
                    {
                        return(0);
                    }
                    else if (dx > dy)
                    {
                        return(-1);
                    }
                    else
                    {
                        return(1);
                    }
                });
                for (int i = 0; i < el.Value.Count(); i++)
                {
                    sortedSchedule[el.Value[i]] = _regimes[_normRegimes.IndexOf(forSort[i])].Select(x => x).ToArray();
                }
            }

            return(sortedSchedule);
        }
        public List<List<double[]>> Balance(Action<string> informationAction = null)
        {
            if (informationAction == null)
                informationAction = (str) => { };

            List<List<double[]>> initialSchedules = null;
            List<double> prevOverfillVolumes = new List<double>();

            List<List<double[]>> ConvertResult()
            {
                if (_sections[0] == null)
                    initialSchedules.RemoveAt(0);
                else if (_sections.Last() == null)
                    initialSchedules.RemoveAt(initialSchedules.Count() - 1);
                return initialSchedules;
            }
            void CalcInitialSchedules()
            {
                initialSchedules = _tempSolutions.Select((x, i) =>
                {
                    if (_sections[i] == null)
                        return AlgorithmHelper.CreateListOfArrays(_period, 1, 0.0);
                    else
                        return _sections[i].GetFullSchedule(CreateInitialSchedule(x));
                }).ToList();
            }
            void CalcOverfill()
            {
                prevOverfillVolumes = new List<double>();
                for (int i = 0; i < initialSchedules.Count() - 1; i++)
                {
                    var reservoirSchedule = GetReservoirSchedule(initialSchedules[i], initialSchedules[i + 1], _tempPumpSchedules[i], _oilStartVolumes[i]);
                    prevOverfillVolumes.Add(GetOverfillVolume(reservoirSchedule, 0, _reservoirVolumes[i]));
                }
            }

            // Сначала без анализа и перестановок
            CreateTempSolution();
            CalcInitialSchedules();
            CalcOverfill();
            if (prevOverfillVolumes.All(x => x == 0.0))
            {
                return ConvertResult();
            }

            int maxIter = 1;
            for (int i = 0; i < maxIter; i++)
            {
                // Перестановки
                CreateTempSolution();
                CalcInitialSchedules();
                initialSchedules = Permute(initialSchedules, 24, 100, informationAction);

                CalcOverfill();
                if (prevOverfillVolumes.All(x => x == 0.0))
                {
                    return ConvertResult();
                }

                // Анализ и изменение объемов
                if (!Analyse(initialSchedules))
                    break;

                CreateTempSolution();
                CalcInitialSchedules();
                CalcOverfill();
                if (prevOverfillVolumes.All(x => x == 0.0))
                {
                    return ConvertResult();
                }
            }

            if (initialSchedules == null)
                return null;
            else
                return ConvertResult();
        }