/// <summary> /// Solves a partial problem. /// </summary> /// <param name="partProblem">DVRP partial problem to solve.</param> /// <param name="timeout">Timeout for computations.</param> /// <returns>Solution of the given problem.</returns> public DvrpSolution Solve(DvrpPartialProblem partProblem, TimeSpan timeout) { var resultCarsRoutes = new List <int> [_dvrpProblem.VehicleCount]; for (var i = 0; i < _dvrpProblem.VehicleCount; i++) { resultCarsRoutes[i] = new List <int>(); } var min = partProblem.ApproximateResult; var n = _dvrpProblem.Requests.Length; var max = new int[n]; max[0] = -1; var part = partProblem.SetBegin; _timer.Reset(); _timer.Start(); // let's check all the partitions for (ulong i = 0; IsLowerSet(part, partProblem.SetEnd); ++i) { if (_timer.Elapsed.TotalSeconds >= timeout.TotalSeconds) { State = UCCTaskSolver.TaskSolver.TaskSolverState.Timeout; break; } for (var j = 1; j < n; ++j) { if (max[j - 1] < part[j - 1]) { max[j] = part[j - 1]; } else { max[j] = max[j - 1]; } } var p = n - 1; while (part[p] == max[p] + 1) { part[p] = 0; p = p - 1; } part[p] = part[p] + 1; var breaking = false; var cap = new List <int>(); var listOfRoutes = new List <List <int> >(); for (var j = 0; j < part.Length; ++j) { if (listOfRoutes.Count == part[j]) { // With this version of algorthm we assume that one car can do only one ride if (listOfRoutes.Count == _dvrpProblem.VehicleCount) { breaking = true; break; } listOfRoutes.Add(new List <int> { j }); cap.Add(_dvrpProblem.Requests[j].Demand); } else { listOfRoutes[part[j]].Add(j); cap[part[j]] += (_dvrpProblem.Requests[j].Demand); // The road has to be served in one ride if (cap[part[j]] >= -_dvrpProblem.VehicleCapacity) { continue; } breaking = true; var tmp = Math.Max(max[j], part[j]); for (var k = j + 1; k < part.Length; k++) { part[k] = ++tmp; } break; } } // if any of partitions doesn't fulfil the requirements if (breaking) { continue; } double distance = 0; var carsRoutes = new List <int> [_dvrpProblem.VehicleCount]; for (var j = 0; j < listOfRoutes.Count; ++j) { distance += _tspSolver.Solve(listOfRoutes[j], min, out carsRoutes[j]); if (distance < min) { continue; } int k = 0; for (int l = 0; l <= j; l++) { k = Math.Max(listOfRoutes[l][listOfRoutes[l].Count - 1], k); } var tmp = Math.Max(max[k], part[k]); for (k += 1; k < part.Length; k++) { part[k] = ++tmp; } break; } if (min <= distance) { continue; } min = distance; for (var j = 0; j < _dvrpProblem.VehicleCount; j++) { if (carsRoutes[j] == null) { resultCarsRoutes[j] = new List <int>(); } else { resultCarsRoutes[j] = new List <int>(carsRoutes[j]); } } } var routes = new int[_dvrpProblem.VehicleCount][]; for (var i = 0; i < routes.Length; i++) { routes[i] = resultCarsRoutes[i].ToArray(); } _timer.Stop(); return(new DvrpSolution(min, routes)); }
/// <summary> /// Divide the problem into partial problems. /// </summary> /// <param name="dvrpProblem">The problem instance to divide.</param> /// <param name="numberOfParts">How many parts to divide into.</param> /// <returns>Output partial problems.</returns> public DvrpPartialProblem[] Divide(DvrpProblem dvrpProblem, int numberOfParts) { // we generate all the partitions // set {{0 0 0 0 0}} represents {{0 1 2 3 4}} // set {{0 1 2 3 4}} represents {{0}{1}{2}{3}{4}} // set {{0 1 2 1 2}} represents {{0}{1 3}{2 4}} // part - current partition // max[i] = Max{max[i-1], part[i-1]} // max[0] = -1 // example: // 0 0 0 // 0 0 1 // 0 1 0 // 0 1 1 // 0 1 2 if (numberOfParts < 1) { throw new ArgumentOutOfRangeException("numberOfParts"); } var n = dvrpProblem.Requests.Length; var part = new int[n]; var max = new int[n]; var maxNumberofSets = TriangularMethodBellNumber(n); var numberOfSetsForThread = maxNumberofSets / (ulong)numberOfParts; var result = new DvrpPartialProblem[numberOfParts]; var solver = new DvrpSolver(dvrpProblem); var approximateResult = solver.SolveApproximately(); for (var i = n - 2; i > -1; --i) { part[i] = 0; } part[n - 1] = max[0] = -1; var partLast = (int[])part.Clone(); ulong j = 0; var k = 0; do { // checking if max[i] == Max{max[i-1], part[i-1]} for (var i = 1; i < n; ++i) { if (max[i - 1] < part[i - 1]) { max[i] = part[i - 1]; } else { max[i] = max[i - 1]; } } // we check if the last elements of the set are in their current maximum // for example // 01200345 p = 7 // 01200340 p = 6 // 01200300 p = 5 // 01200000 p = 4 // and now we can increment element for after following loop // 01201000 var p = n - 1; while (part[p] == max[p] + 1) { part[p] = 0; p = p - 1; } #region optimalization // now it is (n^2) insted of (B*n) if (p <= n - 2 && p > 1 && CheckZeros(part, p, n)) { var tmp = CalculateCombinations(max[p], p, n); if (tmp > numberOfSetsForThread - j - 1) { part[p] = part[p] + 1; ++j; } else { part[p] = max[p] + 1; for (var i = p + 1; i < n; i++) { part[i] = part[i - 1] + 1; } j += tmp; } } else if (p == n - 1 && part[p] == 0) { var tmp = (int)Math.Min(numberOfSetsForThread - j, (double)max[p] + 1); part[p] = tmp; j += (ulong)part[p]; } else { part[p] = part[p] + 1; ++j; } #endregion if (j == numberOfSetsForThread) { result[k] = new DvrpPartialProblem(partLast, approximateResult, j, part); partLast = (int[])part.Clone(); ++k; j = 0; if (k == numberOfParts - 1) { break; } } // ReSharper disable once LoopVariableIsNeverChangedInsideLoop } while (part[n - 1] != n - 1); for (var i = 0; i < n; i++) { part[i] = i; } result[k] = new DvrpPartialProblem(partLast, approximateResult, maxNumberofSets - (ulong)k * numberOfSetsForThread, part); return(result); }
/// <summary> /// Divide the problem into partial problems. /// </summary> /// <param name="dvrpProblem">The problem instance to divide.</param> /// <param name="numberOfParts">How many parts to divide into.</param> /// <returns>Output partial problems.</returns> public DvrpPartialProblem[] Divide(DvrpProblem dvrpProblem, int numberOfParts) { // we generate all the partitions // set {{0 0 0 0 0}} represents {{0 1 2 3 4}} // set {{0 1 2 3 4}} represents {{0}{1}{2}{3}{4}} // set {{0 1 2 1 2}} represents {{0}{1 3}{2 4}} // part - current partition // max[i] = Max{max[i-1], part[i-1]} // max[0] = -1 // example: // 0 0 0 // 0 0 1 // 0 1 0 // 0 1 1 // 0 1 2 if (numberOfParts < 1) throw new ArgumentOutOfRangeException("numberOfParts"); var n = dvrpProblem.Requests.Length; var part = new int[n]; var max = new int[n]; var maxNumberofSets = TriangularMethodBellNumber(n); var numberOfSetsForThread = maxNumberofSets/(ulong) numberOfParts; var result = new DvrpPartialProblem[numberOfParts]; var solver = new DvrpSolver(dvrpProblem); var approximateResult = solver.SolveApproximately(); for (var i = n - 2; i > -1; --i) part[i] = 0; part[n - 1] = max[0] = -1; var partLast = (int[]) part.Clone(); ulong j = 0; var k = 0; do { // checking if max[i] == Max{max[i-1], part[i-1]} for (var i = 1; i < n; ++i) { if (max[i - 1] < part[i - 1]) max[i] = part[i - 1]; else max[i] = max[i - 1]; } // we check if the last elements of the set are in their current maximum // for example // 01200345 p = 7 // 01200340 p = 6 // 01200300 p = 5 // 01200000 p = 4 // and now we can increment element for after following loop // 01201000 var p = n - 1; while (part[p] == max[p] + 1) { part[p] = 0; p = p - 1; } #region optimalization // now it is (n^2) insted of (B*n) if (p <= n - 2 && p > 1 && CheckZeros(part, p, n)) { var tmp = CalculateCombinations(max[p], p, n); if (tmp > numberOfSetsForThread - j - 1) { part[p] = part[p] + 1; ++j; } else { part[p] = max[p] + 1; for (var i = p + 1; i < n; i++) { part[i] = part[i - 1] + 1; } j += tmp; } } else if (p == n - 1 && part[p] == 0) { var tmp = (int) Math.Min(numberOfSetsForThread - j, (double) max[p] + 1); part[p] = tmp; j += (ulong) part[p]; } else { part[p] = part[p] + 1; ++j; } #endregion if (j == numberOfSetsForThread) { result[k] = new DvrpPartialProblem(partLast, approximateResult, j, part); partLast = (int[]) part.Clone(); ++k; j = 0; if (k == numberOfParts - 1) { break; } } // ReSharper disable once LoopVariableIsNeverChangedInsideLoop } while (part[n - 1] != n - 1); for (var i = 0; i < n; i++) { part[i] = i; } result[k] = new DvrpPartialProblem(partLast, approximateResult, maxNumberofSets - (ulong) k*numberOfSetsForThread, part); return result; }
/// <summary> /// Solves a partial problem. /// </summary> /// <param name="partProblem">DVRP partial problem to solve.</param> /// <param name="timeout">Timeout for computations.</param> /// <returns>Solution of the given problem.</returns> public DvrpSolution Solve(DvrpPartialProblem partProblem, TimeSpan timeout) { var resultCarsRoutes = new List<int>[_dvrpProblem.VehicleCount]; for (var i = 0; i < _dvrpProblem.VehicleCount; i++) { resultCarsRoutes[i] = new List<int>(); } var min = partProblem.ApproximateResult; var n = _dvrpProblem.Requests.Length; var max = new int[n]; max[0] = -1; var part = partProblem.SetBegin; _timer.Reset(); _timer.Start(); // let's check all the partitions for (ulong i = 0; IsLowerSet(part, partProblem.SetEnd); ++i) { if (_timer.Elapsed.TotalSeconds >= timeout.TotalSeconds) { State = UCCTaskSolver.TaskSolver.TaskSolverState.Timeout; break; } for (var j = 1; j < n; ++j) { if (max[j - 1] < part[j - 1]) max[j] = part[j - 1]; else max[j] = max[j - 1]; } var p = n - 1; while (part[p] == max[p] + 1) { part[p] = 0; p = p - 1; } part[p] = part[p] + 1; var breaking = false; var cap = new List<int>(); var listOfRoutes = new List<List<int>>(); for (var j = 0; j < part.Length; ++j) { if (listOfRoutes.Count == part[j]) { // With this version of algorthm we assume that one car can do only one ride if (listOfRoutes.Count == _dvrpProblem.VehicleCount) { breaking = true; break; } listOfRoutes.Add(new List<int> { j }); cap.Add(_dvrpProblem.Requests[j].Demand); } else { listOfRoutes[part[j]].Add(j); cap[part[j]] += (_dvrpProblem.Requests[j].Demand); // The road has to be served in one ride if (cap[part[j]] >= -_dvrpProblem.VehicleCapacity) continue; breaking = true; var tmp = Math.Max(max[j], part[j]); for (var k = j + 1; k < part.Length; k++) { part[k] = ++tmp; } break; } } // if any of partitions doesn't fulfil the requirements if (breaking) continue; double distance = 0; var carsRoutes = new List<int>[_dvrpProblem.VehicleCount]; for (var j = 0; j < listOfRoutes.Count; ++j) { distance += _tspSolver.Solve(listOfRoutes[j], min, out carsRoutes[j]); if (distance < min) continue; int k = 0; for (int l = 0; l <= j; l++) { k = Math.Max(listOfRoutes[l][listOfRoutes[l].Count - 1], k); } var tmp = Math.Max(max[k], part[k]); for (k += 1; k < part.Length; k++) { part[k] = ++tmp; } break; } if (min <= distance) continue; min = distance; for (var j = 0; j < _dvrpProblem.VehicleCount; j++) { if (carsRoutes[j] == null) resultCarsRoutes[j] = new List<int>(); else resultCarsRoutes[j] = new List<int>(carsRoutes[j]); } } var routes = new int[_dvrpProblem.VehicleCount][]; for (var i = 0; i < routes.Length; i++) { routes[i] = resultCarsRoutes[i].ToArray(); } _timer.Stop(); return new DvrpSolution(min, routes); }