예제 #1
0
 private bool Matches(Expression <Action> expression)
 {
     this.state = CreateCall(expression);
     return(this.state.Matches());
 }
 private bool Matches(Expression<Action> expression)
 {
     this.state = CreateCall(expression);
     return this.state.Matches();
 }
예제 #3
0
 private static IEnumerable <ArgumentInfo> GetExpressionArguments(MethodCallExpression expression)
 {
     return(ConstraintState.GetArgumentInfos(expression.Arguments, expression.Method.GetParameters()));
 }
예제 #4
0
        private Solution CreateInitialSolution()
        {
            const int chunkSize     = 256;
            var       hardPenalty   = 0;
            var       softPenalty   = 0;
            var       classStates   = new ClassState[Classes.Length];
            var       studentStates = new StudentState[Students.Length];

            for (var i = 0; i < classStates.Length; i++)
            {
                var classData = Classes[i];
                classStates[i] = new ClassState(
                    PullOne(classData.PossibleRooms, 1),
                    PullOne(classData.PossibleSchedules, 1),
                    0, 0, 0, 0);
            }

            var totalPenaltyStudent      = 0;
            var totalPenaltyTime         = 0;
            var totalPenaltyRoom         = 0;
            var totalPenaltyDistribution = 0;

            for (var i = 0; i < studentStates.Length; i++)
            {
                var studentData      = Students[i];
                var enrollmentStates = new List <EnrollmentState>();
                var classesSoFar     = new List <(Schedule schedule, int room)>();
                var conflicts        = 0;
                foreach (var courseId in studentData.Courses)
                {
                    var course          = Courses[courseId];
                    var chain           = course.ClassChains[i % course.ClassChains.Length];
                    var enrollmentState = new EnrollmentState(chain.ConfigIndex, chain.Indexes);
                    enrollmentStates.Add(enrollmentState);
                    var enrolledSubparts = enrollmentState.Subparts;
                    var config           = course.Configurations[chain.ConfigIndex];
                    for (var j = 0; j < enrolledSubparts.Length; j++)
                    {
                        var subpart     = config.Subparts[j];
                        var classIndex  = enrolledSubparts[j];
                        var classObject = subpart.Classes[classIndex];
                        var classData   = Classes[classObject.Id];
                        var classState  = classStates[classObject.Id];
                        classStates[classObject.Id] = classState = classState
                                                                   .WithAttendees(classState.Attendees + 1, 0, 0);
                        var schedule = classData.PossibleSchedules[classState.Time];
                        var room     = classState.Room >= 0 ? classData.PossibleRooms[classState.Room].Id : -1;

                        foreach (var(prevSchedule, prevRoom) in classesSoFar)
                        {
                            var travelTime = room >= 0 && prevRoom >= 0 ? TravelTimes[room, prevRoom] : 0;
                            if (schedule.Overlaps(prevSchedule, travelTime))
                            {
                                conflicts++;
                            }
                        }

                        classesSoFar.Add((schedule, room));
                    }
                }

                softPenalty         += conflicts * StudentPenalty;
                totalPenaltyStudent += conflicts;
                studentStates[i]     = new StudentState(enrollmentStates.ToArray(), conflicts);
            }

            var classConflicts   = 0;
            var roomsUnavailable = 0;
            var classOverflows   = 0;

            for (var i = 0; i < classStates.Length; i++)
            {
                var state     = classStates[i];
                var classData = Classes[i];
                var schedule  = classData.PossibleSchedules[state.Time];

                softPenalty      += TimePenalty * schedule.Penalty;
                totalPenaltyTime += schedule.Penalty;

                var roomId = -1;
                var roomCapacityPenalty    = 0;
                var roomUnavailablePenalty = 0;
                var classCapacityPenalty   = state.Attendees > classData.Capacity
                    ? Solution.ClassCapacityOverflowBase + (state.Attendees - classData.Capacity) / Solution.ClassCapacityOverflowRate
                    : 0;
                classOverflows += classCapacityPenalty;

                if (state.Room >= 0)
                {
                    var roomAssignment = classData.PossibleRooms[state.Room];
                    roomId = roomAssignment.Id;
                    var room = Rooms[roomId];
                    roomCapacityPenalty = state.Attendees > room.Capacity
                        ? Solution.RoomCapacityOverflowBase + (state.Attendees - room.Capacity) / Solution.RoomCapacityOverflowRate
                        : 0;

                    hardPenalty += roomCapacityPenalty;

                    roomUnavailablePenalty = 0;
                    foreach (var unavailableSchedule in room.UnavailableSchedules)
                    {
                        if (schedule.Overlaps(unavailableSchedule))
                        {
                            roomUnavailablePenalty = 1;
                            break;
                        }
                    }

                    hardPenalty      += roomUnavailablePenalty;
                    roomsUnavailable += roomUnavailablePenalty;

                    softPenalty      += RoomPenalty * roomAssignment.Penalty;
                    totalPenaltyRoom += roomAssignment.Penalty;
                }

                for (var j = 0; j < i; j++)
                {
                    var otherClassState = classStates[j];
                    var otherClassData  = Classes[j];
                    if (otherClassState.Room < 0)
                    {
                        continue;
                    }

                    var otherRoomId = otherClassData.PossibleRooms[otherClassState.Room].Id;
                    if (roomId != otherRoomId)
                    {
                        continue;
                    }

                    var otherSchedule = otherClassData.PossibleSchedules[otherClassState.Time];
                    if (schedule.Overlaps(otherSchedule))
                    {
                        classConflicts++;
                    }
                }

                classStates[i] = new ClassState(
                    state.Room,
                    state.Time,
                    state.Attendees,
                    classCapacityPenalty,
                    roomCapacityPenalty,
                    roomUnavailablePenalty);
            }

            hardPenalty += classConflicts;

            var constraintStates = new ConstraintState[Constraints.Length];

            var partialSolution = new Solution(
                this,
                hardPenalty,
                softPenalty,
                classOverflows,
                classConflicts,
                roomsUnavailable,
                new ChunkedArray <ClassState>(classStates, chunkSize),
                new ChunkedArray <StudentState>(studentStates, chunkSize),
                new ChunkedArray <ConstraintState>(constraintStates, chunkSize));

            foreach (var constraint in Constraints)
            {
                var(h, s) = constraint.Evaluate(this, partialSolution);
                var normalized = (constraint.Required ? (double)h : s) /
                                 constraint.WorstCase;
                constraintStates[constraint.Id] = new ConstraintState(h, s, normalized);
                hardPenalty += h;
                softPenalty += s * DistributionPenalty;
                totalPenaltyDistribution += s;
            }

            var initialSolution = new Solution(
                this,
                hardPenalty,
                softPenalty,
                classOverflows,
                classConflicts,
                roomsUnavailable,
                new ChunkedArray <ClassState>(classStates, chunkSize),
                new ChunkedArray <StudentState>(studentStates, chunkSize),
                new ChunkedArray <ConstraintState>(constraintStates, chunkSize));

            return(initialSolution);
        }