Exemplo n.º 1
0
    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>
        /// Sets the SantaVisitStartingTimes variable
        /// </summary>
        /// <param name="day"></param>
        /// <param name="santa"></param>
        public void SetVisitStartingTimes(int day, int santa)
        {
            var s        = GetSantaId(day, santa);
            var sequence = solverVariables.VisitSequences[s];
            var c        = model.Count(sequence);

            var visitStartingTimeSelector = model.Function((i, prev) =>
                                                           model.If(i == 0,
                                                                    solverVariables.OptimizationInput.Days[day].from + solverVariables.SantaWaitBeforeStart[s] + solverVariables.DistanceFromHomeArray[sequence[i]],
                                                                    prev + solverVariables.VisitDurationArray[sequence[i - 1]] + solverVariables.DistanceArray[sequence[i - 1], sequence[i]] + solverVariables.SantaWaitBetweenVisitArray[s][sequence[i]]
                                                                    )
                                                           );

            var visitStartingTime = model.Array(model.Range(0, c), visitStartingTimeSelector);

            solverVariables.SantaVisitStartingTimes[s] = visitStartingTime;
        }
Exemplo n.º 3
0
        public SolverVariables(LSModel model, int numberOfRoutes, List <Visit> visits, int[,] routeCosts, OptimizationInput optimizationInput, int numberOfFakeSantas)
        {
            Model              = model;
            Visits             = visits;
            NumberOfRoutes     = numberOfRoutes;
            OptimizationInput  = optimizationInput;
            NumberOfFakeSantas = numberOfFakeSantas;
            NumberOfSantas     = optimizationInput.Santas.Length;

            SantaUsed                = new LSExpression[numberOfRoutes];
            VisitSequences           = new LSExpression[numberOfRoutes + 1];
            SantaWalkingTime         = new LSExpression[numberOfRoutes];
            SantaRouteTime           = new LSExpression[numberOfRoutes];
            SantaVisitDurations      = new LSExpression[numberOfRoutes];
            SantaDesiredDuration     = new LSExpression[numberOfRoutes];
            SantaUnavailableDuration = new LSExpression[numberOfRoutes];
            SantaVisitStartingTimes  = new LSExpression[numberOfRoutes];

            SantaOvertime              = new LSExpression[numberOfRoutes];
            SantaWaitBeforeStart       = new LSExpression[numberOfRoutes];
            SantaWaitBetweenVisit      = new LSExpression[numberOfRoutes][];
            SantaWaitBetweenVisitArray = new LSExpression[numberOfRoutes];

            int numberOfVisits = Visits.Count;
            var longestDay     = OptimizationInput.Days.Max(d => d.to - d.from);

            for (var k = 0; k < numberOfRoutes; k++)
            {
                VisitSequences[k]       = Model.List(numberOfVisits);
                SantaOvertime[k]        = Model.Int(0, int.MaxValue);
                SantaWaitBeforeStart[k] = Model.Int(0, longestDay);

                SantaWaitBetweenVisit[k] = new LSExpression[numberOfVisits];
                for (var i = 0; i < SantaWaitBetweenVisit[k].Length; i++)
                {
                    SantaWaitBetweenVisit[k][i] = Model.Int(0, longestDay);
                }

                SantaWaitBetweenVisitArray[k] = Model.Array(SantaWaitBetweenVisit[k]);
            }

            // overflow for unused santa breaks
            VisitSequences[numberOfRoutes] = model.List(numberOfVisits);

            DistanceArray         = model.Array(RouteCostJagged(Visits, routeCosts));
            DistanceFromHomeArray = model.Array(Visits.Select(v => v.WayCostFromHome).ToArray());
            DistanceToHomeArray   = model.Array(Visits.Select(v => v.WayCostToHome).ToArray());
            VisitDurationArray    = model.Array(Visits.Select(v => v.Duration).ToArray());

            // desired
            var visitsOnlyDesired = visits
                                    .Select(v =>
                                            // fake arr
                                            v.Desired.Length == 0
                        ? new[] { new[] { -1, -1 } }
                        : v.Desired.Select(d => new[] { d.from, d.to }).ToArray()
                                            )
                                    .ToArray();

            VisitDesiredArray      = model.Array(visitsOnlyDesired);
            VisitDesiredCountArray = model.Array(visits.Select(v => v.Desired.Length).ToArray());

            // unavailable
            var visitsOnlyUnavailable = visits
                                        .Select(v =>
                                                // fake arr
                                                v.Unavailable.Length == 0
                        ? new[] { new[] { -1, -1 } }
                        : v.Unavailable.Select(d => new[] { d.from, d.to }).ToArray()
                                                )
                                        .ToArray();

            VisitUnavailableArray      = model.Array(visitsOnlyUnavailable);
            VisitUnavailableCountArray = model.Array(visits.Select(v => v.Unavailable.Length).ToArray());
        }