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); }
//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))); }
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; }
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)); }
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)); }
public FakeTechnologicalSectionAlgorithm(List <double[]> schedule) { _schedule = schedule; _regimes = AlgorithmHelper.RemoveDuplicates(_schedule); _normRegimes = AlgorithmHelper.NormalizeByComponents(_regimes); Period = schedule.Count(); Dimension = schedule[0].Count(); }
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); }
/// <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)); }
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(); }