void Solve(int limit) { // Declares the optimization model. LSModel model = localsolver.GetModel(); trucksUsed = new LSExpression[nbTrucks]; customersSequences = new LSExpression[nbTrucks]; routeDistances = new LSExpression[nbTrucks]; // Sequence of customers visited by each truck. for (int k = 0; k < nbTrucks; k++) { customersSequences[k] = model.List(nbCustomers); } // All customers must be visited by the trucks model.Constraint(model.Partition(customersSequences)); // Create demands and distances as arrays to be able to access it with an "at" operator LSExpression demandsArray = model.Array(demands); LSExpression distanceWarehouseArray = model.Array(distanceWarehouses); LSExpression distanceArray = model.Array(distanceMatrix); for (int k = 0; k < nbTrucks; k++) { LSExpression sequence = customersSequences[k]; LSExpression c = model.Count(sequence); // A truck is used if it visits at least one customer trucksUsed[k] = c > 0; // The quantity needed in each route must not exceed the truck capacity LSExpression demandSelector = model.Function(i => demandsArray[sequence[i]]); LSExpression routeQuantity = model.Sum(model.Range(0, c), demandSelector); model.Constraint(routeQuantity <= truckCapacity); // Distance travelled by truck k LSExpression distSelector = model.Function(i => distanceArray[sequence[i - 1], sequence[i]]); routeDistances[k] = model.Sum(model.Range(1, c), distSelector) + model.If(c > 0, distanceWarehouseArray[sequence[0]] + distanceWarehouseArray[sequence[c - 1]], 0); } nbTrucksUsed = model.Sum(trucksUsed); totalDistance = model.Sum(routeDistances); // Objective: minimize the number of trucks used, then minimize the distance traveled model.Minimize(nbTrucksUsed); model.Minimize(totalDistance); model.Close(); // Parameterizes the solver. LSPhase phase = localsolver.CreatePhase(); phase.SetTimeLimit(limit); localsolver.Solve(); }
/// <summary> /// adds a constraint that time after the day-end is considered overtime /// </summary> /// <param name="day"></param> /// <param name="santa"></param> public void AddOvertimeConstraint(int day, int santa) { var s = GetSantaId(day, santa); var sequence = solverVariables.VisitSequences[s]; var c = model.Count(sequence); model.Constraint(model.If(solverVariables.SantaUsed[s], solverVariables.SantaVisitStartingTimes[s][c - 1] + solverVariables.VisitDurationArray[sequence[c - 1]] + solverVariables.DistanceToHomeArray[sequence[c - 1]], 0) <= solverVariables.OptimizationInput.Days[day].to + solverVariables.SantaOvertime[s]); }