org.optaplanner.examples.curriculumcourse.persistence.CurriculumCourseImporter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of optaplanner-examples Show documentation
Show all versions of optaplanner-examples Show documentation
OptaPlanner solves planning problems.
This lightweight, embeddable planning engine implements powerful and scalable algorithms
to optimize business resource scheduling and planning.
This module contains the examples which demonstrate how to use it in a normal Java application.
package org.optaplanner.examples.curriculumcourse.persistence;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.optaplanner.examples.common.persistence.AbstractTxtSolutionImporter;
import org.optaplanner.examples.common.persistence.SolutionConverter;
import org.optaplanner.examples.curriculumcourse.app.CurriculumCourseApp;
import org.optaplanner.examples.curriculumcourse.domain.Course;
import org.optaplanner.examples.curriculumcourse.domain.CourseSchedule;
import org.optaplanner.examples.curriculumcourse.domain.Curriculum;
import org.optaplanner.examples.curriculumcourse.domain.Day;
import org.optaplanner.examples.curriculumcourse.domain.Lecture;
import org.optaplanner.examples.curriculumcourse.domain.Period;
import org.optaplanner.examples.curriculumcourse.domain.Room;
import org.optaplanner.examples.curriculumcourse.domain.Teacher;
import org.optaplanner.examples.curriculumcourse.domain.Timeslot;
import org.optaplanner.examples.curriculumcourse.domain.UnavailablePeriodPenalty;
public class CurriculumCourseImporter extends AbstractTxtSolutionImporter {
private static final String INPUT_FILE_SUFFIX = "ctt";
public static void main(String[] args) {
SolutionConverter converter = SolutionConverter.createImportConverter(CurriculumCourseApp.DATA_DIR_NAME,
new CurriculumCourseImporter(), new CurriculumCourseSolutionFileIO());
converter.convertAll();
}
@Override
public String getInputFileSuffix() {
return INPUT_FILE_SUFFIX;
}
@Override
public TxtInputBuilder createTxtInputBuilder() {
return new CurriculumCourseInputBuilder();
}
public static class CurriculumCourseInputBuilder extends TxtInputBuilder {
@Override
public CourseSchedule readSolution() throws IOException {
CourseSchedule schedule = new CourseSchedule(0L);
// Name: ToyExample
schedule.setName(readStringValue("Name:"));
// Courses: 4
int courseListSize = readIntegerValue("Courses:");
// Rooms: 2
int roomListSize = readIntegerValue("Rooms:");
// Days: 5
int dayListSize = readIntegerValue("Days:");
// Periods_per_day: 4
int timeslotListSize = readIntegerValue("Periods_per_day:");
// Curricula: 2
int curriculumListSize = readIntegerValue("Curricula:");
// Constraints: 8
int unavailablePeriodPenaltyListSize = readIntegerValue("Constraints:");
Map courseMap = readCourseListAndTeacherList(
schedule, courseListSize);
readRoomList(
schedule, roomListSize);
Map, Period> periodMap = createPeriodListAndDayListAndTimeslotList(
schedule, dayListSize, timeslotListSize);
readCurriculumList(
schedule, courseMap, curriculumListSize);
readUnavailablePeriodPenaltyList(
schedule, courseMap, periodMap, unavailablePeriodPenaltyListSize);
readEmptyLine();
readConstantLine("END\\.");
createLectureList(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 {}.",
getInputId(),
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 Map readCourseListAndTeacherList(
CourseSchedule schedule, int courseListSize) throws IOException {
Map courseMap = new HashMap<>(courseListSize);
Map teacherMap = new HashMap<>();
List courseList = new ArrayList<>(courseListSize);
readEmptyLine();
readConstantLine("COURSES:");
for (int i = 0; i < courseListSize; i++) {
// Courses: <# Lectures> <# Students>
String line = bufferedReader.readLine();
String[] lineTokens = splitBySpacesOrTabs(line, 5);
Course course = new Course(i, lineTokens[0], findOrCreateTeacher(teacherMap, lineTokens[1]),
Integer.parseInt(lineTokens[2]), Integer.parseInt(lineTokens[4]), Integer.parseInt(lineTokens[3]));
courseList.add(course);
courseMap.put(course.getCode(), course);
}
schedule.setCourseList(courseList);
List teacherList = new ArrayList<>(teacherMap.values());
schedule.setTeacherList(teacherList);
return courseMap;
}
private Teacher findOrCreateTeacher(Map teacherMap, String code) {
Teacher teacher = teacherMap.get(code);
if (teacher == null) {
int id = teacherMap.size();
teacher = new Teacher(id, code);
teacherMap.put(code, teacher);
}
return teacher;
}
private void readRoomList(CourseSchedule schedule, int roomListSize)
throws IOException {
readEmptyLine();
readConstantLine("ROOMS:");
List roomList = new ArrayList<>(roomListSize);
for (int i = 0; i < roomListSize; i++) {
// Rooms:
String line = bufferedReader.readLine();
String[] lineTokens = splitBySpacesOrTabs(line, 2);
Room room = new Room(i, lineTokens[0], Integer.parseInt(lineTokens[1]));
roomList.add(room);
}
schedule.setRoomList(roomList);
}
private Map, Period> createPeriodListAndDayListAndTimeslotList(CourseSchedule schedule, int dayListSize,
int timeslotListSize) {
int periodListSize = dayListSize * timeslotListSize;
Map, Period> periodMap = new HashMap<>(periodListSize);
List dayList = new ArrayList<>(dayListSize);
for (int i = 0; i < dayListSize; i++) {
Day day = new Day(i);
day.setPeriodList(new ArrayList<>(timeslotListSize));
dayList.add(day);
}
schedule.setDayList(dayList);
List timeslotList = new ArrayList<>(timeslotListSize);
for (int i = 0; i < timeslotListSize; i++) {
Timeslot timeslot = new Timeslot(i);
timeslotList.add(timeslot);
}
schedule.setTimeslotList(timeslotList);
List periodList = new ArrayList<>(periodListSize);
for (int i = 0; i < dayListSize; i++) {
Day day = dayList.get(i);
for (int j = 0; j < timeslotListSize; j++) {
Period period = new Period((long) i * timeslotListSize + j, day, timeslotList.get(j));
periodList.add(period);
periodMap.put(Arrays.asList(i, j), period);
}
}
schedule.setPeriodList(periodList);
return periodMap;
}
private void readCurriculumList(CourseSchedule schedule,
Map courseMap, int curriculumListSize) throws IOException {
readEmptyLine();
readConstantLine("CURRICULA:");
List curriculumList = new ArrayList<>(curriculumListSize);
for (int i = 0; i < curriculumListSize; i++) {
// Curricula: <# Courses> ...
String line = bufferedReader.readLine();
String[] lineTokens = splitBySpacesOrTabs(line);
if (lineTokens.length < 2) {
throw new IllegalArgumentException("Read line (" + line
+ ") is expected to contain at least 2 tokens.");
}
Curriculum curriculum = new Curriculum(i, lineTokens[0]);
int coursesInCurriculum = Integer.parseInt(lineTokens[1]);
if (lineTokens.length != (coursesInCurriculum + 2)) {
throw new IllegalArgumentException("Read line (" + line + ") is expected to contain "
+ (coursesInCurriculum + 2) + " tokens.");
}
for (int j = 2; j < lineTokens.length; j++) {
Course course = courseMap.get(lineTokens[j]);
if (course == null) {
throw new IllegalArgumentException("Read line (" + line + ") uses an unexisting course("
+ lineTokens[j] + ").");
}
course.getCurriculumSet().add(curriculum);
}
curriculumList.add(curriculum);
}
schedule.setCurriculumList(curriculumList);
}
private void readUnavailablePeriodPenaltyList(CourseSchedule schedule, Map courseMap,
Map, Period> periodMap, int unavailablePeriodPenaltyListSize)
throws IOException {
readEmptyLine();
readConstantLine("UNAVAILABILITY_CONSTRAINTS:");
List penaltyList = new ArrayList<>(
unavailablePeriodPenaltyListSize);
for (int i = 0; i < unavailablePeriodPenaltyListSize; i++) {
// Unavailability_Constraints:
String line = bufferedReader.readLine();
String[] lineTokens = splitBySpacesOrTabs(line, 3);
int dayIndex = Integer.parseInt(lineTokens[1]);
int timeslotIndex = Integer.parseInt(lineTokens[2]);
Period period = periodMap.get(Arrays.asList(dayIndex, timeslotIndex));
if (period == null) {
throw new IllegalArgumentException("Read line (" + line + ") uses an unexisting period("
+ dayIndex + " " + timeslotIndex + ").");
}
UnavailablePeriodPenalty penalty = new UnavailablePeriodPenalty(i, courseMap.get(lineTokens[0]), period);
penaltyList.add(penalty);
}
schedule.setUnavailablePeriodPenaltyList(penaltyList);
}
private void createLectureList(CourseSchedule schedule) {
List courseList = schedule.getCourseList();
List lectureList = new ArrayList<>(courseList.size());
long id = 0L;
for (Course course : courseList) {
for (int i = 0; i < course.getLectureSize(); i++) {
Lecture lecture = new Lecture(id, course, i, false);
id++;
// Notice that we leave the PlanningVariable properties on null
lectureList.add(lecture);
}
}
schedule.setLectureList(lectureList);
}
}
}