private bool FindSolutions(IEnumerable<Subject> subjects) { var subject = subjects.FirstOrDefault(); if (subject == null) { double weight = GetSolutionWeight(currentSolution, groups); if (bestSolutions.Count == 0) { bestSolutions.AddFirst(new Tuple<ScheduledTimeSlot[], double>(GetCurrentSolutionArray(), weight)); } else { LinkedListNode<Tuple<ScheduledTimeSlot[], double>> scheduledTimeSlot; for (scheduledTimeSlot = bestSolutions.First; scheduledTimeSlot != null; scheduledTimeSlot = scheduledTimeSlot.Next) { if (weight >= scheduledTimeSlot.Value.Item2) { ScheduledTimeSlot[] copy = new ScheduledTimeSlot[currentSolution.Count]; currentSolution.CopyTo(copy, 0); bestSolutions.AddBefore(scheduledTimeSlot, new Tuple<ScheduledTimeSlot[], double>(copy, weight)); if (bestSolutions.Count > 10) { bestSolutions.RemoveLast(); } break; } } } return weight != Double.MaxValue; } foreach (var room in rooms. Where(r => r.types.IsSupersetOf(subject.roomTypes)). Where(r => r.capacity >= subject.attendingPeopleCount). Where(r => subject.teachers.All(t => t.requirements.requiredRooms.Contains(r)))) { var roomAvailabilities = room.availability.SelectMany(a => a.GetAllWindows(subject.duration)).ToList(); foreach (var windowTimeSlot in roomAvailabilities) { int dayOfWeek = (int) windowTimeSlot.Day - 1; if (subject.GetGroups().All(g => groupAvailabilities[g][dayOfWeek].Any(a => a.Includes(windowTimeSlot)))) { if (subject.teachers.All(t => t.requirements.weight != 1 || t.requirements.availableTimeSlots.Any(a => a.Includes(windowTimeSlot)))) { TimeSlot.RemoveTimeSlotFromAvailability(room.availability, windowTimeSlot); foreach (var group in subject.GetGroups()) { TimeSlot.RemoveTimeSlotFromAvailability(groupAvailabilities[group][dayOfWeek], windowTimeSlot); } currentSolution.AddLast(new ScheduledTimeSlot(subject, room, windowTimeSlot, subject.GetGroups())); if (!FindSolutions(subjects.Skip(1))) { return false; } currentSolution.RemoveLast(); foreach (var group in subject.GetGroups()) { TimeSlot.AddTimeSlotToAvailability(groupAvailabilities[group][(int)windowTimeSlot.Day - 1], windowTimeSlot); } TimeSlot.AddTimeSlotToAvailability(room.availability, windowTimeSlot); } } } } return true; }
private ScheduledTimeSlot[] GetCurrentSolutionArray() { ScheduledTimeSlot[] copy = new ScheduledTimeSlot[currentSolution.Count]; currentSolution.CopyTo(copy, 0); return copy; }