/// <summary> /// Calculates the weight for a part of the tour including the turns at first and last position. /// </summary> /// <param name="part">The part to calculate for.</param> /// <param name="timeBefore">The time when arriving at the first customer, excluding the turn at that first customer.</param> public int TimeAndViolationsForPart(IEnumerable <int> part, float timeBefore, out float time, out float waitTime, out float violatedTime, ref bool[] validFlags) { var times = this.Times; var windows = this.Windows; var turnPenalties = this.TurnPenalties; time = timeBefore; violatedTime = 0f; waitTime = 0f; var violated = 0; var previousFrom = int.MaxValue; foreach (var directedId in part) { // extract turns and stuff from directed id. int arrivalId, departureId, id, turn; DirectedHelper.ExtractAll(directedId, out arrivalId, out departureId, out id, out turn); // add the weight from the previous customer to the current one. var turnPenalty = 0f; if (previousFrom != int.MaxValue) { // there is a previous, add the travel time. time = time + times[previousFrom][arrivalId]; // and keep the turn penalty. turnPenalty += turnPenalties[turn]; } else { // first customer. // add turn penalty at first customer. time += turnPenalties[DirectedHelper.ExtractTurn(directedId)]; } // check the windows (before turn-penalties). var window = windows[id]; validFlags[id] = true; if (window.Max < (time + waitTime)) { // ok, unfeasible. violatedTime += (time + waitTime) - window.Max; validFlags[id] = false; violated++; } if (window.Min > (time + waitTime)) { // wait here! waitTime += (window.Min - (time + waitTime)); } // add the turn penalty. time += turnPenalty; previousFrom = departureId; } time = time - timeBefore; // correct the time again, the time returned is the time of only this part. return(violated); }
/// <summary> /// Calculates total time and violations if the given id was moved after 'before'. Assumes the tour is closed. /// </summary> public int TimeAndViolations(IEnumerable <int> tour, out float time, out float waitTime, out float violatedTime, ref bool[] validFlags) { var times = this.Times; var windows = this.Windows; var turnPenalties = this.TurnPenalties; time = 0f; violatedTime = 0f; waitTime = 0f; var violated = 0; var previousFrom = int.MaxValue; var firstTo = int.MaxValue; var first = Constants.NOT_SET; foreach (var directedId in tour) { if (first == Constants.NOT_SET) { first = directedId; } // extract turns and stuff from directed id. int arrivalId, departureId, id, turn; DirectedHelper.ExtractAll(directedId, out arrivalId, out departureId, out id, out turn); // add the weight from the previous customer to the current one. var turnPenalty = 0f; if (previousFrom != int.MaxValue) { // there is a previous, add the travel time. time = time + times[previousFrom][arrivalId]; // and keep the turn penalty. turnPenalty += turnPenalties[turn]; } else { // first customer. firstTo = arrivalId; } // check the windows (before turn-penalties). var window = windows[id]; validFlags[id] = true; if (window.Max < (time + waitTime)) { // ok, unfeasible. violatedTime += (time + waitTime) - window.Max; validFlags[id] = false; violated++; } if (window.Min > (time + waitTime)) { // wait here! waitTime += (window.Min - (time + waitTime)); } // add the turn penalty. time += turnPenalty; previousFrom = departureId; } // add the weight between last and first. if (previousFrom != int.MaxValue) { time = time + times[previousFrom][firstTo]; // add turn penalty at first customer. time += turnPenalties[DirectedHelper.ExtractTurn(first)]; } return(violated); }