opta CurriculumCourse 例子,参数初始化


// ############################################################################
// Hard constraints
// ############################################################################


// Lectures: A missing or extra lecture of a course.
// This hard constraint is built-in: the correct number of Lecture's is created


// Conflicts: Two conflicting lectures in the same period.
// Three conflicting lectures count as 3 violations: one for each pair.
rule "conflictingLecturesDifferentCourseInSamePeriod"
    when
        $courseConflict : CourseConflict($leftCourse : leftCourse, $rightCourse : rightCourse)
        $leftLecture : Lecture(course == $leftCourse, $period : period, period != null)
        $rightLecture : Lecture(course == $rightCourse, period == $period, this != $leftLecture)
    then
        scoreHolder.addHardConstraintMatch(kcontext, - $courseConflict.getConflictCount());
end
rule "conflictingLecturesSameCourseInSamePeriod"
    when
        Lecture($leftId : id, $leftCourse : course, $period : period, period != null)
        Lecture(course == $leftCourse, period == $period, id > $leftId)
    then
        scoreHolder.addHardConstraintMatch(kcontext, - (1 + $leftCourse.getCurriculumList().size()));
end


// RoomOccupancy: Two lectures in the same room at the same period.
// Any extra lecture in the same period and room counts as one more violation.
rule "roomOccupancy"
    when
        Lecture($leftId : id, period != null, $period : period, room != null, $room : room)
        // $leftLecture has lowest id of the period+room combo
        not Lecture(period == $period, room == $room, id < $leftId)
        // rightLecture has the same period
        Lecture(period == $period, room == $room, id > $leftId, $rightId : id)
    then
        scoreHolder.addHardConstraintMatch(kcontext, -1);
end


// Availabilities: Each lecture in a period unavailable for that course.
rule "unavailablePeriodPenalty"
    when
        UnavailablePeriodPenalty($course : course, $period : period)
        Lecture(course == $course, period == $period)
    then
        scoreHolder.addHardConstraintMatch(kcontext, -10);
end


// ############################################################################
// Soft constraints
// ############################################################################


// RoomCapacity: For each lecture, the number of students that attend the course should be less or equal
// than the number of seats of all the rooms that host its lectures.
// Each student above the capacity counts as 1 point of penalty.
rule "roomCapacity"
    when
        $room : Room($capacity : capacity)
        Lecture(room == $room, studentSize > $capacity, $studentSize : studentSize)
    then
        scoreHolder.addSoftConstraintMatch(kcontext, ($capacity - $studentSize));
end


// MinimumWorkingDays: The lectures of each course should be spread into a minimum number of days.
// Each day below the minimum counts as 5 points of penalty.
rule "minimumWorkingDays"
    when
        $course : Course($minWorkingDaySize : minWorkingDaySize)
        accumulate(
            $day : Day()
            and exists Lecture(course == $course, day == $day);
            $dayCount : count($day);
            $dayCount < $minWorkingDaySize
        )
        // An uninitialized schedule should have no constraints broken
        exists Lecture(course == $course, period != null)
    then
        scoreHolder.addSoftConstraintMatch(kcontext, (($dayCount.intValue() - $minWorkingDaySize) * 5));
end


// CurriculumCompactness: Lectures belonging to a curriculum should be adjacent
// to each other (i.e., in consecutive periods).
// For a given curriculum we account for a violation every time there is one lecture not adjacent
// to any other lecture within the same day.
// Each isolated lecture in a curriculum counts as 2 points of penalty.
rule "curriculumCompactness"
    when
        $curriculum : Curriculum()


        Lecture(curriculumList contains $curriculum,
            $day : day, $timeslotIndex : timeslotIndex, period != null
        )
        not Lecture(curriculumList contains $curriculum,
            day == $day, timeslotIndex == ($timeslotIndex - 1)
        )
        not Lecture(curriculumList contains $curriculum,
            day == $day, timeslotIndex == ($timeslotIndex + 1)
        )
    then
        scoreHolder.addSoftConstraintMatch(kcontext, -2);
end


// RoomStability: All lectures of a course should be given in the same room.
// Each distinct room used for the lectures of a course, but the first, counts as 1 point of penalty.
rule "roomStability"
    when
        $course : Course()
        accumulate(
            $room : Room()
            and exists Lecture(course == $course, room == $room);
            $roomCount : count($room);
            $roomCount > 1
        )
    then
        scoreHolder.addSoftConstraintMatch(kcontext, -($roomCount.intValue() - 1));
end


  


 public CourseSchedule createCourseSchedule(String fileName, int teacherListSize, int curriculumListSize, int courseListSize, int lectureListSize, int roomListSize) {

        random = new Random(37);
        CourseSchedule schedule = new CourseSchedule();
        schedule.setId(0L);


        createDayList(schedule);
        createTimeslotList(schedule);
        createPeriodList(schedule);
        createTeacherList(schedule, teacherListSize);
        createCourseList(schedule, courseListSize);
        createLectureList(schedule, lectureListSize);
        createRoomList(schedule, roomListSize);
        createCurriculumList(schedule, curriculumListSize);
        createUnavailablePeriodPenaltyList(schedule);


        int possibleForOneLectureSize = schedule.getPeriodList().size() * schedule.getRoomList().size();
        BigInteger possibleSolutionSize = BigInteger.valueOf(possibleForOneLectureSize).pow(
                schedule.getLectureList().size());
        logger.info("CourseSchedule {} has {} teachers, {} curricula, {} courses, {} lectures," +
                        " {} periods, {} rooms and {} unavailable period constraints with a search space of {}.",
                fileName,
                schedule.getTeacherList().size(),
                schedule.getCurriculumList().size(),
                schedule.getCourseList().size(),
                schedule.getLectureList().size(),
                schedule.getPeriodList().size(),
                schedule.getRoomList().size(),
                schedule.getUnavailablePeriodPenaltyList().size(),
                getFlooredPossibleSolutionSize(possibleSolutionSize));
        return schedule;
    }


    private void createDayList(CourseSchedule schedule) {
        List<Day> dayList = new ArrayList<>(DAY_LIST_SIZE);
        for (int i = 0; i < DAY_LIST_SIZE; i++) {
            Day day = new Day();
            day.setId((long) i);
            day.setDayIndex(i);
            day.setPeriodList(new ArrayList<>(TIMESLOT_LIST_SIZE));
            dayList.add(day);
        }
        schedule.setDayList(dayList);
    }


    private void createTimeslotList(CourseSchedule schedule) {
        List<Timeslot> timeslotList = new ArrayList<>(TIMESLOT_LIST_SIZE);
        for (int i = 0; i < TIMESLOT_LIST_SIZE; i++) {
            Timeslot timeslot = new Timeslot();
            timeslot.setId((long) i);
            timeslot.setTimeslotIndex(i);
            timeslotList.add(timeslot);
        }
        schedule.setTimeslotList(timeslotList);
    }


    private void createPeriodList(CourseSchedule schedule) {
        List<Period> periodList = new ArrayList<>(schedule.getDayList().size() * schedule.getTimeslotList().size());
        long periodId = 0L;
        for (Day day : schedule.getDayList()) {
            for (Timeslot timeslot : schedule.getTimeslotList()) {
                if (day.getDayIndex() == 2 && timeslot.getTimeslotIndex() >= 4) {
                    // No lectures Wednesday afternoon
                    continue;
                }
                Period period = new Period();
                period.setId(periodId);
                periodId++;
                period.setDay(day);
                day.getPeriodList().add(period);
                period.setTimeslot(timeslot);
                periodList.add(period);
            }
        }
        schedule.setPeriodList(periodList);
    }


    private void createTeacherList(CourseSchedule schedule, int teacherListSize) {
        List<Teacher> teacherList = new ArrayList<>(teacherListSize);
        teacherNameGenerator.predictMaximumSizeAndReset(teacherListSize);
        for (int i = 0; i < teacherListSize; i++) {
            Teacher teacher = new Teacher();
            teacher.setId((long) i);
            teacher.setCode(teacherNameGenerator.generateNextValue());
            teacherList.add(teacher);
        }
        schedule.setTeacherList(teacherList);
    }


    private void createCourseList(CourseSchedule schedule, int courseListSize) {
        List<Teacher> teacherList = schedule.getTeacherList();
        List<Course> courseList = new ArrayList<>(courseListSize);
        Set<String> codeSet = new HashSet<>();
        for (int i = 0; i < courseListSize; i++) {
            Course course = new Course();
            course.setId((long) i);
            String code = (i < courseCodes.length * 2)
                    ? courseCodes[i % courseCodes.length]
                    : courseCodes[random.nextInt(courseCodes.length)];
            StringDataGenerator codeSuffixGenerator = new StringDataGenerator("")
                    .addAToZPart(true, 0);
            if (courseListSize >= courseCodes.length) {
                String codeSuffix = codeSuffixGenerator.generateNextValue();
                while (codeSet.contains(code + codeSuffix)) {
                    codeSuffix = codeSuffixGenerator.generateNextValue();
                }
                code = code + codeSuffix;
                codeSet.add(code);
            }
            course.setCode(code);
            Teacher teacher = (i < teacherList.size() * 2)
                    ? teacherList.get(i % teacherList.size())
                    : teacherList.get(random.nextInt(teacherList.size()));
            course.setTeacher(teacher);
            course.setLectureSize(0);
            course.setMinWorkingDaySize(1);
            course.setCurriculumList(new ArrayList<>());
            course.setStudentSize(0);
            courseList.add(course);
        }
        schedule.setCourseList(courseList);
    }


    private void createLectureList(CourseSchedule schedule, int lectureListSize) {
        List<Course> courseList = schedule.getCourseList();
        List<Lecture> lectureList = new ArrayList<>(lectureListSize);
        for (int i = 0; i < lectureListSize; i++) {
            Lecture lecture = new Lecture();
            lecture.setId((long) i);
            Course course = (i < courseList.size() * 2)
                    ? courseList.get(i % courseList.size())
                    : courseList.get(random.nextInt(courseList.size()));
            lecture.setCourse(course);
            lecture.setLectureIndexInCourse(course.getLectureSize());
            course.setLectureSize(course.getLectureSize() + 1);
            lecture.setPinned(false);
            lectureList.add(lecture);
        }
        schedule.setLectureList(lectureList);


    }


    private void createRoomList(CourseSchedule schedule, int roomListSize) {
        List<Room> roomList = new ArrayList<>(roomListSize);
        for (int i = 0; i < roomListSize; i++) {
            Room room = new Room();
            room.setId((long) i);
            room.setCode("R" + ((i / 50 * 100) + 1 + i));
            room.setCapacity(roomCapacityOptions[random.nextInt(roomCapacityOptions.length)]);
            roomList.add(room);
        }
        schedule.setRoomList(roomList);
    }


    private void createCurriculumList(CourseSchedule schedule, int curriculumListSize) {
        int maximumCapacity = schedule.getRoomList().stream().mapToInt(Room::getCapacity).max().getAsInt();
        List<Course> courseList = schedule.getCourseList();
        List<Curriculum> curriculumList = new ArrayList<>(curriculumListSize);
        StringDataGenerator codeGenerator = new StringDataGenerator("")
                .addAToZPart(true, 0).addAToZPart(false, 1).addAToZPart(false, 1).addAToZPart(false, 1);
        codeGenerator.predictMaximumSizeAndReset(curriculumListSize);
        for (int i = 0; i < curriculumListSize; i++) {
            Curriculum curriculum = new Curriculum();
            curriculum.setId((long) i);
            curriculum.setCode("Group " + codeGenerator.generateNextValue());
            // The studentSize is more likely to be 15 than 5 or 25
            int studentSize = 5 + random.nextInt(10) + random.nextInt(10);


            List<Course> courseSubList = courseList.stream()
                    .filter(course -> course.getStudentSize() + studentSize < maximumCapacity)
                    .collect(Collectors.toList());
            Collections.shuffle(courseSubList, random);


            int lectureCount = 0;
            for (Course course : courseSubList) {
                lectureCount += course.getLectureSize();
                if (lectureCount > PERIOD_LIST_SIZE) {
                    break;
                }
                course.getCurriculumList().add(curriculum);
                course.setStudentSize(course.getStudentSize() + studentSize);
            }


            curriculumList.add(curriculum);
        }
        schedule.setCurriculumList(curriculumList);
    }


    private void createUnavailablePeriodPenaltyList(CourseSchedule schedule) {
        List<Course> courseList = schedule.getCourseList();
        List<Period> periodList = schedule.getPeriodList();
        List<UnavailablePeriodPenalty> unavailablePeriodPenaltyList = new ArrayList<>(courseList.size());
        long penaltyId = 0L;
        for (Course course : courseList) {
            UnavailablePeriodPenalty penalty = new UnavailablePeriodPenalty();
            penalty.setId(penaltyId);
            penaltyId++;
            penalty.setCourse(course);
            penalty.setPeriod(periodList.get(random.nextInt(periodList.size())));
            unavailablePeriodPenaltyList.add(penalty);
        }
        schedule.setUnavailablePeriodPenaltyList(unavailablePeriodPenaltyList);
    }

猜你喜欢

转载自blog.csdn.net/seaReal1/article/details/80652214