Пример #1
0
 public LaneSchedulerAction(int leftmostLane, LaneSchedulerReservation reservation, double weight)
 {
     this.leftmostLane = leftmostLane;
     this.lowestTimeSlot = reservation.StartTimeSlot;
     this.reservation = reservation;
     this.weight = weight;
     this.numLanes = reservation.NumberOfLanes;
     this.numTimeSlots = reservation.NumberOfTimeSlots;
 }
Пример #2
0
        public static List<LaneSchedulerReservation> GetAlternativeReservations(LaneSchedulerState state, LaneSchedulerReservation reservation)
        {
            List<LaneSchedulerReservation> reservations = new List<LaneSchedulerReservation>();

            if (reservation.StartTimeSlot - 1 > 0)
            {
                LaneSchedulerReservation altReservation1 = new LaneSchedulerReservation(reservation.Id, reservation.NumberOfLanes, reservation.NumberOfTimeSlots, reservation.StartTimeSlot - 1);
                List<LaneSchedulerAction> actions = LaneScheduler.Expand(state, altReservation1);
                if (actions.Count > 0)
                {
                    reservations.Add(altReservation1);
                }
                int numTimeSlots = reservation.NumberOfTimeSlots - 1;
                while (numTimeSlots > 0)
                {
                    LaneSchedulerReservation altReservation2 = new LaneSchedulerReservation(reservation.Id, reservation.NumberOfLanes, numTimeSlots, reservation.StartTimeSlot - 1);
                    List<LaneSchedulerAction> actions2 = LaneScheduler.Expand(state, altReservation2);
                    if (actions2.Count > 0)
                    {
                        reservations.Add(altReservation2);
                    }
                    numTimeSlots--;
                }
            }

            if (reservation.StartTimeSlot + 1 < state.numberOfTimeSlots)
            {
                LaneSchedulerReservation altReservation1 = new LaneSchedulerReservation(reservation.Id, reservation.NumberOfLanes, reservation.NumberOfTimeSlots, reservation.StartTimeSlot + 1);
                List<LaneSchedulerAction> actions = LaneScheduler.Expand(state, altReservation1);
                if (actions.Count > 0)
                {
                    reservations.Add(altReservation1);
                }
                int numTimeSlots = reservation.NumberOfTimeSlots - 1;
                while (numTimeSlots > 0)
                {
                    LaneSchedulerReservation altReservation2 = new LaneSchedulerReservation(reservation.Id, reservation.NumberOfLanes, numTimeSlots, reservation.StartTimeSlot + 1);
                    List<LaneSchedulerAction> actions2 = LaneScheduler.Expand(state, altReservation2);
                    if (actions2.Count > 0)
                    {
                        reservations.Add(altReservation2);
                    }
                    numTimeSlots--;
                }
            }

            return reservations;
        }
Пример #3
0
 public static List<LaneSchedulerAction> Expand(LaneSchedulerState state, LaneSchedulerReservation reservation)
 {
     List<LaneSchedulerAction> actions = new List<LaneSchedulerAction>();
     if (state.IsPossible(reservation))
     {
         for (int lane = 0; lane < state.numberOfLanes; lane++)
         {
             AppWeightPair appWeightPair = state.IsApplicable(lane, reservation.NumberOfLanes, reservation.NumberOfTimeSlots, reservation.StartTimeSlot);
             if (appWeightPair.applicable)
             {
                 actions.Add(new LaneSchedulerAction(lane, reservation, appWeightPair.weight));
             }
         }
     }
     return actions;
 }
Пример #4
0
        public static bool Test_n_reservations(int numberOfLanes, int numberOfTimeSlots, int numberOfVisitors, int runLimit)
        {
            Debug.WriteLine("Testing scheduling of " + numberOfVisitors + " visitors in " + numberOfLanes + " lanes and " + numberOfTimeSlots + " timeslots");
            LaneWearData.Populate(numberOfLanes);
            List<LaneSchedulerReservation> reservations = new List<LaneSchedulerReservation>();
            // Reservation(int id, int numLanes, int numTimeSlots, int startTimeSlot)
            bool run = true;
            //State emptyState = new State(numberOfLanes, numberOfTimeSlots, reservations);
            LaneSchedulerState state = new LaneSchedulerState(numberOfLanes, numberOfTimeSlots, reservations);
            LaneSchedulerState newState = null;
            int i = 0;
            int visitors = 0;
            int runs = 0;
            long timeSpent = 0;
            Random random = new Random();
            while (run)
            {
                int numVisitors = 4;

                int numTimeSlots = random.Next(1, 3);
                int startTimeSlot = 6; //  random.Next(0, numberOfTimeSlots);
                if (random.Next(0, 100) < 10)
                { // 10 percent will be parties and outings
                    numVisitors = random.Next(5, 41);
                }
                else
                {
                    numVisitors = random.Next(3, 7);
                }

                if (random.Next(0, 100) < 15)
                {
                    startTimeSlot = random.Next(0, numberOfTimeSlots);
                }
                else
                {
                    startTimeSlot = random.Next(2, numberOfTimeSlots - 2);
                }
                int numLanes = 0;
                if (numVisitors % 6 == 0)
                {
                    numLanes = numVisitors / 6;
                }
                else
                {
                    numLanes = (numVisitors / 6) + 1;
                }

                long time1 = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
                int id = i + 1;
                LaneSchedulerReservation reservation = new LaneSchedulerReservation(id, numLanes, numTimeSlots, startTimeSlot);
                Debug.WriteLine("Making reservation id: " + id + " of " + numLanes + " lanes for " + numTimeSlots + " hours, at timeslot " + startTimeSlot);

                List<LaneSchedulerReservation> newReservations = new List<LaneSchedulerReservation>(reservations);
                newReservations.Add(reservation);
                //emptyState = new State(numberOfLanes, numberOfTimeSlots, newReservations);
                LaneSchedulerStateReservationsPair result = LaneScheduler.Search(state, reservations, reservation);
                newState = result.state;

                long time2 = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
                timeSpent = time2 - time1;
                Debug.WriteLine("    Scheduling took: " + timeSpent + " miliseconds");
                if (newState != null)
                {
                    Debug.WriteLine("    It SUCCEEDED!!!!!!!!");
                    Debug.WriteLine(newState.ToString());

                    reservations = newReservations;
                    state = newState;
                    visitors = visitors + numVisitors;
                    Debug.WriteLine("Have now scheduled for: " + visitors + " visitors");
                    i++;
                }
                else
                {
                    Debug.WriteLine("    It failed. Alternative reservations are:");
                    for (int j = 0; j < result.reservations.Count; j++)
                    {
                        Debug.WriteLine("        Reservation for " + result.reservations[j].NumberOfLanes + " lanes at slot: " + result.reservations[j].StartTimeSlot + " for " + result.reservations[j].NumberOfTimeSlots + " hours");
                    }
                }
                if (visitors > numberOfVisitors)
                {
                    run = false;
                }
                if (runs > runLimit)
                {
                    run = false;
                }
                runs++;
            }
            Debug.WriteLine("The last scheduling took: " + timeSpent + " miliseconds");
            if (state != null)
            {
                Debug.WriteLine(state.ToString());
            }
            return true;
        }
Пример #5
0
        public static LaneSchedulerStateReservationsPair Search(LaneSchedulerState state, List<LaneSchedulerReservation> reservations, LaneSchedulerReservation newReservation)
        {
            LaneScheduler.closedStateList = new Dictionary<string, int>();
            Debug.WriteLine("Adding new Reservation");
            if (!state.IsPossible(newReservation))
            {
                Debug.WriteLine("    It failed the first check");
                // get other reservations
                return new LaneSchedulerStateReservationsPair(null, LaneScheduler.GetAlternativeReservations(state, newReservation));
            }
            // if it can be applied easily
            List<LaneSchedulerAction> actions = Expand(state, newReservation);
            actions = (from y in actions
                       select y).OrderBy(y => y.weight).ToList<LaneSchedulerAction>();
            if (actions.Count > 0)
            {
                state.Apply(actions[0]);
                Debug.WriteLine("    The reservation was straight forward");
                return new LaneSchedulerStateReservationsPair(state, new List<LaneSchedulerReservation>());
            }

            // else, search

            // cut the relevant piece out of the state, so we end up with three pieces.
            // Solve the middle piece, and add it to the top and bottom piece.
            //List<State> statePieces = state.cutInPieces(newReservation);

            List<LaneSchedulerReservation> newReservations = new List<LaneSchedulerReservation>(reservations);
            newReservations.Add(newReservation);

            long time1 = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
            LaneSchedulerState emptyState = new LaneSchedulerState(state.numberOfLanes, state.numberOfTimeSlots, newReservations);
            LaneSchedulerState newState = LaneScheduler.RecursiveSearch(emptyState, newReservations, 0, 100000, 0);

            long time2 = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
            long runTime = time2 - time1;
            Debug.WriteLine("    Search took: " + runTime + " ms");
            if (newState != null)
            {
                Debug.WriteLine("    Returning state");
                return new LaneSchedulerStateReservationsPair(newState, new List<LaneSchedulerReservation>());
            }
            else
            {
                // get other reservations
                Debug.WriteLine("    Returning other reservations");
                return new LaneSchedulerStateReservationsPair(null, LaneScheduler.GetAlternativeReservations(state, newReservation));
            }
        }
Пример #6
0
        public List<LaneSchedulerState> CutInPieces(LaneSchedulerReservation reservation)
        {
            List<LaneSchedulerState> stateList = new List<LaneSchedulerState>();

            // detect cutting lines
            // find cutting line for upper part
            int upperCut = -1;
            for (int i = reservation.StartTimeSlot + reservation.NumberOfTimeSlots; i < this.numberOfTimeSlots; i++)
            {
                bool foundAny = false;
                for (int j = 0; j < this.numberOfLanes; j++)
                {
                    if (this.state[i, j] == this.state[i + 1, j] || this.state[i, j] == this.state[i - 1, j])
                    {
                        foundAny = true;
                    }
                    if (!foundAny)
                    {
                        upperCut = i;
                        break;
                    }
                }
            }
            // find cutting line for lower part
            int lowerCut = -1;
            for (int i = reservation.StartTimeSlot - 1; i >= 0; i--)
            {
                bool foundAny = false;
                for (int j = 0; j < this.numberOfLanes; j++)
                {
                    if (this.state[i, j] == this.state[i + 1, j] || this.state[i, j] == this.state[i - 1, j])
                    {
                        foundAny = true;
                    }
                    if (!foundAny)
                    {
                        lowerCut = i;
                        break;
                    }
                }
            }

            // do the cutting
            LaneSchedulerState stateUpper = new LaneSchedulerState(this.numberOfLanes, this.numberOfTimeSlots, new List<LaneSchedulerReservation>());
            stateUpper.weight = this.weight;
            stateUpper.weight = this.weight;
            stateUpper.state = new int[numberOfTimeSlots, numberOfLanes];

            LaneSchedulerState stateMiddle = new LaneSchedulerState(this.numberOfLanes, this.numberOfTimeSlots, new List<LaneSchedulerReservation>());
            stateMiddle.weight = this.weight;
            stateMiddle.weight = this.weight;
            stateMiddle.state = new int[numberOfTimeSlots, numberOfLanes];

            LaneSchedulerState stateLower = new LaneSchedulerState(this.numberOfLanes, this.numberOfTimeSlots, new List<LaneSchedulerReservation>());
            stateLower.weight = this.weight;
            stateLower.weight = this.weight;
            stateLower.state = new int[numberOfTimeSlots, numberOfLanes];

            // Populate them

            for (int i = 0; i < this.numberOfTimeSlots; i++)
            {
                for (int j = 0; j < this.numberOfLanes; j++)
                {
                    if (i <= lowerCut)
                    {
                        stateLower.state[i, j] = this.state[i, j];
                    }
                    else if (j >= upperCut)
                    {
                        stateMiddle.state[i, j] = this.state[i, j];
                    }
                    else
                    {
                        stateUpper.state[i, j] = this.state[i, j];
                    }
                }
            }
            stateList.Add(stateUpper);
            stateList.Add(stateMiddle);
            stateList.Add(stateLower);
            return stateList;
        }
Пример #7
0
 public String ReservationRepr(LaneSchedulerReservation reservation)
 {
     StringBuilder builder = new StringBuilder();
     builder.Append(reservation.Id);
     builder.Append(",");
     builder.Append(reservation.NumberOfLanes);
     builder.Append(",");
     builder.Append(reservation.NumberOfTimeSlots);
     builder.Append(",");
     builder.Append(reservation.StartTimeSlot);
     builder.Append("->");
     for (int i = reservation.StartTimeSlot - reservation.NumberOfTimeSlots; i < reservation.StartTimeSlot + reservation.NumberOfTimeSlots; i++)
     {
         if (i < this.numberOfTimeSlots && i >= 0)
         {
             for (int j = 0; j < this.numberOfLanes; j++)
             {
                 builder.Append(this.state[i, j]);
                 builder.Append(".");
             }
             builder.Append("/");
         }
     }
     return builder.ToString();
 }
Пример #8
0
 public bool IsPossible(LaneSchedulerReservation reservation)
 {
     for (int i = reservation.StartTimeSlot; i < reservation.NumberOfTimeSlots + reservation.StartTimeSlot; i++)
     {
         if (i >= this.numberOfTimeSlots)
         {
             return false;
         }
         int numFreeCells = 0;
         for (int j = 0; j < this.numberOfLanes; j++)
         {
             if (this.state[i, j] == 0)
             {
                 numFreeCells++;
             }
         }
         if (numFreeCells < reservation.NumberOfLanes)
         {
             return false;
         }
     }
     return true;
 }
Пример #9
0
        public double GetReservationWeight(LaneSchedulerReservation reservation)
        {
            double weight = 0.0f;

            for (int i = reservation.StartTimeSlot; i < reservation.StartTimeSlot + reservation.NumberOfTimeSlots; i++)
            {
                weight = Math.Max(weight, this.GetCellWeight(i));
            }
            weight += 1 / reservation.NumberOfLanes;
            return weight;
        }
Пример #10
0
        /// <summary>
        /// Determines whether the new reservation <paramref name="reservation"/> is possible
        /// based on the current reservation schedule for the day of that reservations
        /// </summary>
        /// <remarks>
        /// The lane scheduler will be queried to check for availablility. While doing this,
        /// all current reservations for that day might be rescheduled, therefore, the new schedule
        /// is returned. This schedule will have to be persisted if the new reservation is acuallly
        /// added to the database.
        /// 
        /// The out paramter "newReservation" will contain an reservation instance ready for persisting
        /// if this is sought.
        /// 
        /// Execptions will be thrown if the reservation does not fit in the current schedule
        /// </remarks>
        /// <param name="reservation">The new reservation</param>
        /// <param name="theReservation">An intance of a reservation, based on the data from <paramref name="reservation"/></param>
        /// <returns>The list of rescheduled reservations and an instance ready to commit in <paramref name="theReservation"/></returns>
        /// <exception cref="ArgumentException">If the <paramref name="reservation"/> is not possible</exception>
        public List<Reservation> Go(ReservationType reservation, out Reservation theReservation, out bool isPossible, out List<LaneSchedulerReservation> suggestions)
        {
            // quick pruning of the result - does the requested timeslot exist at all??
            TimeSlot startTimeSlot = timeSlotRepos.GetAll().FindTimeSlotStartingAt(reservation.TimeOfDay);
            if (startTimeSlot == null)
            {
                throw new ArgumentException("Reservation is not possible as the timeslot does not exist", "timeSlot");
            }

            var reservations = reservationRepos.GetAll().FindReservationsByDate(reservation.PlayAt);

            // convert these into a format the scheduler understands...
            List<LaneSchedulerReservation> schedulerReservations;
            var convertToState = ServiceLocator.Current.GetInstance<ReservationsToLaneSchedulerState>();
            var schedulerState = convertToState.Convert(reservations.ToList(), out schedulerReservations);

            LaneSchedulerReservation newReservation = new LaneSchedulerReservation()
            {
                Id = -1,
                NumberOfLanes = (int)Math.Ceiling(reservation.NumberOfPlayers / 6.0m),
                NumberOfTimeSlots = reservation.HowManyHours,
                StartTimeSlot = startTimeSlot.Id - 1
            };

            // do the scheduling
            var newState = LaneScheduler.Search(schedulerState, schedulerReservations, newReservation);

            if (newState.state == null)
            {

                suggestions = newState.reservations;
                isPossible = false;
                theReservation = null;
                return null;

            }
            suggestions = null;
            // The scheduler attempts to place the reservation +/- one time slot in the schedule if it's full,
            // so we have to try and handle that
            var convertToReservation = ServiceLocator.Current.GetInstance<LaneSchedulerStateToReservations>();
            var rescheduledReservations = convertToReservation.Convert(newState.state, out theReservation);
            theReservation.NumberOfPlayers = reservation.NumberOfPlayers;
            theReservation.PlayAt = reservation.PlayAt;
            theReservation.Name = reservation.Name;
            theReservation.PhoneNumber = reservation.PhoneNumber;
            theReservation.Status = ReservationStatus.Pending;
            theReservation.CreatedAt = DateTime.Now;

            // now that we have the actual reservation, we can check
            // the added time-slots against the requested timeslot
            if (theReservation.TimeSlots[0].Start != startTimeSlot.Start)
            {
                isPossible = false;
            }
            else
            {
                isPossible = true;
            }

            return rescheduledReservations;
        }