处理大学课程时间表(JAVA)遗传算法的软约束

时间:2018-08-05 14:45:07

标签: serialization genetic-algorithm timetable

我目前正在从事我的毕业项目,该项目正在使用遗传算法解决大学课程排课问题。 在这个项目中,我使用了metaheuristic network data sets,其中包含一些硬约束和软约束。 我的程序能够处理所有硬约束,并且我使用了本地搜索交叉运算符来满足所有硬约束。 现在我有一个处理软约束的问题:

学生在当天的最后一个时段上课。 一个学生连续上两节课。 一个学生一天上一堂课。

首先,我在深度复制包含其他对象的计划对象时遇到问题,我使用了序列化方法,但是它给我中型和大型数据集的堆栈溢出错误。 其次,我想问一下处理软约束的最佳算法或搜索技术是什么。

这是我的第一个计算违反软约束的次数的函数

public int CalcViolations() {
    violation = 0;
    int consecutiveClasses;
    boolean oneClassPenalty;
    int studentNo=data.getStudents().size();
    for(int i=0;i<studentNo;i++){
        int stCoSize=data.getStudents().get(i).getCourseRecord().size();
        consecutiveClasses = 0;
        for(int j=0;j<stCoSize;j++) {
            if (data.getStudents().get(i).getCourseRecord().get(j).getMeetingTime().getId() % 9 == 0) {
                violation++;
            }
            for (int n = 0; n < stCoSize; n++) {
                    if (n != j) {
                        if (data.getStudents().get(i).getCourseRecord().get(j).getMeetingTime().getId() % 9 != 0 && data.getStudents().get(i).getCourseRecord().get(n).getMeetingTime().getId() % 9 != 0) {
                        if (Math.abs((data.getStudents().get(i).getCourseRecord().get(j).getMeetingTime().getId()) - (data.getStudents().get(i).getCourseRecord().get(n).getMeetingTime().getId())) == 1) {
                            consecutiveClasses++;
                        }
                    }
                }
            }
            if (consecutiveClasses > 2) {
                violation++;
            }
        }
        for(int j=0;j<data.getStudents().get(i).getCourseRecord().size();j++){
            oneClassPenalty=true;
            if(j==0){
                if(data.getStudents().get(i).getCourseRecord().get(j).getMeetingTime().getDay()==data.getStudents().get(i).getCourseRecord().get(j+1).getMeetingTime().getDay())
                    oneClassPenalty=false;
            }
            if(j>0){
                if((data.getStudents().get(i).getCourseRecord().get(j).getMeetingTime().getDay()==data.getStudents().get(i).getCourseRecord().get(j-1).getMeetingTime().getDay()))
                    oneClassPenalty=false;
                if(j+1 < data.getStudents().get(i).getCourseRecord().size()){
                    if((data.getStudents().get(i).getCourseRecord().get(j).getMeetingTime().getDay()==data.getStudents().get(i).getCourseRecord().get(j+1).getMeetingTime().getDay())) oneClassPenalty=false;
                }
            }
            if(oneClassPenalty) {
                violation++;
            }
        }
    }
    return violation;

}

这是用于处理违反软约束的方法

public Schedule SoftConstraints(Schedule s) {
    int consecutiveClasses;
    boolean oneClassPenalty;
    for(int i=0;i<data.getStudents().size();i++){
        consecutiveClasses = 0;
        for(int j=0;j<data.getStudents().get(i).getCourseRecord().size();j++) {
            for (int n = 0; n < data.getStudents().get(i).getCourseRecord().size(); n++) {
                if (n != j) {
                    if (data.getStudents().get(i).getCourseRecord().get(j).getMeetingTime().getId() % 9 != 0 && data.getStudents().get(i).getCourseRecord().get(n).getMeetingTime().getId() % 9 != 0) {
                        if (Math.abs((data.getStudents().get(i).getCourseRecord().get(j).getMeetingTime().getId()) - (data.getStudents().get(i).getCourseRecord().get(n).getMeetingTime().getId())) == 1) {
                            consecutiveClasses++;
                            if (consecutiveClasses > 2) {
                                int c = s.getClasses().indexOf(data.getStudents().get(i).getCourseRecord().get(j));
                                s=shuffle(s, c);
                            }
                        }
                    }
                }
                if (data.getStudents().get(i).getCourseRecord().get(j).getMeetingTime().getId() % 9 == 0) {
                    int c = s.getClasses().indexOf(data.getStudents().get(i).getCourseRecord().get(j));
                    s=shuffle(s, c);
                }
            }
        }
        for(int j=0;j<data.getStudents().get(i).getCourseRecord().size();j++){
            oneClassPenalty=true;
            if(j==0){
                if(data.getStudents().get(i).getCourseRecord().get(j).getMeetingTime().getDay()==data.getStudents().get(i).getCourseRecord().get(j+1).getMeetingTime().getDay())
                    oneClassPenalty=false;
            }
            if( j > 0){
                if((data.getStudents().get(i).getCourseRecord().get(j).getMeetingTime().getDay()==data.getStudents().get(i).getCourseRecord().get(j-1).getMeetingTime().getDay()))
                    oneClassPenalty=false;
                if(j+1<data.getStudents().get(i).getCourseRecord().size()){
                    if((data.getStudents().get(i).getCourseRecord().get(j).getMeetingTime().getDay()==data.getStudents().get(i).getCourseRecord().get(j+1).getMeetingTime().getDay())) oneClassPenalty = false;
                }
            }
            if(oneClassPenalty) {
                int c = s.getClasses().indexOf(data.getStudents().get(i).getCourseRecord().get(j));
                    shuffle(s,c);
            }
        }
    }
    return s;
}

private ArrayList<MeetingTime> getStudentOccupyTime(Schedule s, Class c){
    ArrayList<MeetingTime> MT=new ArrayList<>();
    for(int i=0;i<c.getCourse().getStudent().size();i++){
        for(int j=0;j<s.getClasses().size();j++){
            for(int n=0;n<s.getClasses().get(j).getCourse().getStudent().size();n++){
                if(s.getClasses().get(j).getCourse().getStudent().get(n)==c.getCourse().getStudent().get(i)){
                    MT.add(s.getClasses().get(j).getMeetingTime());
                }
            }
        }
    }
    Set<MeetingTime> removeDups = new LinkedHashSet<>(MT);
    MT.clear();
    MT.addAll(removeDups);
    return MT;
}

private ArrayList<MeetingTime> getStudentFreeTime(ArrayList<MeetingTime> MT){
    ArrayList<MeetingTime> studentFreeTime=new ArrayList<>();
    for(int i=0;i<data.getMeetingTimes().size();i++){
        if(!MT.contains(data.getMeetingTimes().get(i))) {
            studentFreeTime.add(data.getMeetingTimes().get(i));
        }
    }
    return studentFreeTime;
}

private ArrayList<Room> ChangeRoomAvailability(Schedule s,int c){
    Room currentRoom=s.getClasses().get(c).getRoom();
    ArrayList<Room> AvailableRooms=new ArrayList<>();
    AvailableRooms.clear();
    for(int r=0;r<data.getRooms().size();r++) {
        if ((data.getRooms().get(r).getFeatures().containsAll(s.getClasses().get(c).getCourse().getFeatures())) && (data.getRooms().get(r).getSeatingCapacity() >= s.getClasses().get(c).getCourse().getMaxNumbOfStudents())) {
            if (data.getRooms().get(r) != currentRoom)
                if(checkAvailability(s,data.getRooms().get(r))) AvailableRooms.add(data.getRooms().get(r));
        }
    }
    return AvailableRooms;
}

private ArrayList<MeetingTime> checkRoomAvailableTime(Schedule s, Room currentRoom){//Room currentRoom=r;
    ArrayList<MeetingTime> RoomOccupyTime=new ArrayList<>();
    ArrayList<MeetingTime> roomAvailableTime=new ArrayList<>();
    roomAvailableTime.clear();
    for (int i = 0; i < s.getClasses().size(); i++) {
        if (s.getClasses().get(i).getRoom() == currentRoom) {
            RoomOccupyTime.add(s.getClasses().get(i).getMeetingTime());
        }
    }
    Set<MeetingTime> removeDups = new LinkedHashSet<>(RoomOccupyTime);
    RoomOccupyTime.clear();
    RoomOccupyTime.addAll(removeDups);
    if(RoomOccupyTime.containsAll(data.getMeetingTimes())) return roomAvailableTime;
    else{
        for(int i=0;i<data.getMeetingTimes().size();i++){
            if(!RoomOccupyTime.contains(data.getMeetingTimes().get(i))){
                roomAvailableTime.add(data.getMeetingTimes().get(i));
            }
        }
        return roomAvailableTime;
    }
}

private Schedule shuffle(Schedule s, int c)  {
    int currentVio=s.getViolation();
    Boolean status=false;
    MeetingTime rand;
    ArrayList<Room> candidateRooms = new ArrayList<>();
    Room newRoom=null;
    ArrayList<MeetingTime> checkedTime = new ArrayList<>();
    ArrayList<MeetingTime> MT;
    ArrayList<MeetingTime> studentAvailableTime;
    ArrayList<MeetingTime> roomAvailableTime;
    ArrayList<MeetingTime> AvailableTime=new ArrayList<>();

    MT=getStudentOccupyTime(s,s.getClasses().get(c));
    studentAvailableTime=getStudentFreeTime(MT);
    roomAvailableTime=checkRoomAvailableTime(s,s.getClasses().get(c).getRoom());
    AvailableTime.clear();
    if(roomAvailableTime.size()>0){
        for (MeetingTime aStudentAvailableTime : studentAvailableTime) {
            if (roomAvailableTime.contains(aStudentAvailableTime))
                AvailableTime.add(aStudentAvailableTime);
        }
    }
    checkedTime.clear();
    if(AvailableTime.size()>0) {
        while (!status ) {
            rand = AvailableTime.get((int) (AvailableTime.size() * Math.random()));
            while (checkedTime.contains(rand)&&checkedTime.size()!=AvailableTime.size()){
                rand = AvailableTime.get((int) (AvailableTime.size() * Math.random()));
            }
            s.getClasses().get(c).setMeetingTime(rand);
            if(!checkedTime.contains(rand)) checkedTime.add(rand);
            if(s.getViolation()<currentVio && s.getFitness()==1.0){
                status=true;
                break;
            }
            if(checkedTime.size()==AvailableTime.size())break;
        }

    }
    if(status){
        return s;
    }
    else ShuffleCourseTime( s, c);
    if(s.getViolation()<currentVio){
        return s;
    }
    else {
        candidateRooms.clear();
        candidateRooms=ChangeRoomAvailability(s,c);
        if(candidateRooms.size()>0){
            newRoom=checkSwapping(s,c,candidateRooms);
        }
        if(candidateRooms.size()>0 && newRoom!=null){
            shuffle(s,c,newRoom);
        }
        return s;
    }
}
private Schedule shuffle(Schedule s, int c, Room r){
    s.getClasses().get(c).setRoom(r);
    MeetingTime rand;
    ArrayList<MeetingTime> MT;
    ArrayList<MeetingTime> studentAvailableTime;
    ArrayList<MeetingTime> roomAvailableTime;
    ArrayList<MeetingTime> AvailableTime=new ArrayList<>();
    MT=getStudentOccupyTime(s,s.getClasses().get(c));
    studentAvailableTime=getStudentFreeTime(MT);
    roomAvailableTime=checkRoomAvailableTime(s,r);
    if(roomAvailableTime.size()>0){
        for (MeetingTime aStudentAvailableTime : studentAvailableTime) {
            if (roomAvailableTime.contains(aStudentAvailableTime))
                AvailableTime.add(aStudentAvailableTime);
        }
    }
    if(AvailableTime.size()>0) {
        rand = AvailableTime.get((int) (AvailableTime.size() * Math.random()));
        s.getClasses().get(c).setMeetingTime(rand);
    }
    return s;
}
private Room checkSwapping(Schedule s,int c,ArrayList<Room> availableRooms){
    ArrayList<MeetingTime> MT;
    ArrayList<MeetingTime> studentAvailableTime;
    Room randomRoom;
    Room NewRoom=null;
    ArrayList<MeetingTime> meetingTime=new ArrayList<>();
    ArrayList<Room> checkRoom=new ArrayList<>();
    ArrayList<MeetingTime> availableTime=new ArrayList<>();
    Boolean status=false;
    MT=getStudentOccupyTime(s,s.getClasses().get(c));
    studentAvailableTime=getStudentFreeTime(MT);
    meetingTime.clear();
    availableTime.clear();
    while (checkRoom.size()!=availableRooms.size()){
        randomRoom=availableRooms.get((int) (availableRooms.size()*Math.random()));
        meetingTime = checkRoomAvailableTime(s, randomRoom);
        for (MeetingTime aStudentAvailableTime : studentAvailableTime) {
            if (meetingTime.contains(aStudentAvailableTime)) {
                availableTime.add(aStudentAvailableTime);
            }
        }
        if(!checkRoom.contains(randomRoom)) checkRoom.add(randomRoom);
        if(availableTime.size()>0){
            NewRoom=randomRoom;
            status=true;
            break;
        }
        if(checkRoom.size()==availableRooms.size()) break;
    }
    if(status) return NewRoom;
    else    return null;
}

public Schedule Serialization(Schedule s){
    Object obj = null;
    try {
        FastByteArrayOutputStream fbos =
                new FastByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(fbos);
        out.writeObject(s);
        out.flush();
        out.close();
        ObjectInputStream in =
                new ObjectInputStream(fbos.getInputStream());
        obj = in.readObject();
    }
    catch(IOException e) {
        e.printStackTrace();
    }
    catch(ClassNotFoundException cnfe) {
        cnfe.printStackTrace();
    }
    return (Schedule) obj;

}

public Schedule ShuffleCourseTime(Schedule s,int c){
    int currentViolation=s.getViolation();
    ArrayList<Class> checkedClass=new ArrayList<>();
    Boolean Status=false;
    Room currentRoom=s.getClasses().get(c).getRoom();
    ArrayList<Class> roomClasses=new ArrayList<>();
    for(int i=0;i<s.getClasses().size();i++){
        if(s.getClasses().get(i).getRoom()==currentRoom&&s.getClasses().get(i)!=s.getClasses().get(c)) roomClasses.add(s.getClasses().get(i));
    }
    while (!Status){
        if(roomClasses.size()==0)break;
        MeetingTime T1=s.getClasses().get(c).getMeetingTime();
        Class c2=roomClasses.get((int) (Math.random() * roomClasses.size()));
        while (checkedClass.contains(c2)&&checkedClass.size()!=roomClasses.size()) {
            c2 = roomClasses.get((int) (Math.random() * roomClasses.size()));
        }
        MeetingTime T2=c2.getMeetingTime();
        s.getClasses().get(c).setMeetingTime(data.getMeetingTimes().get((int)(data.getMeetingTimes().size()*Math.random())));
        s.getClasses().get(s.getClasses().indexOf(c2)).setMeetingTime(data.getMeetingTimes().get((int)(data.getMeetingTimes().size()*Math.random())));
        if(s.getFitness()==1){
            if(s.getViolation()<currentViolation){
                Status=true;
                break;
            }
        }
        s.getClasses().get(c).setMeetingTime(T1);
        s.getClasses().get(s.getClasses().indexOf(c2)).setMeetingTime(T2);
        if(!checkedClass.contains(c2))checkedClass.add(c2);
        if (checkedClass.size()==roomClasses.size())break;
    }
    if(Status)return s;
    else return s;

}

此功能可以处理小型数据集的第一个和第二个软约束,但是对于中型和大型数据集,此功能花费的时间太长,这也是我认为是由于深度复制所致。

0 个答案:

没有答案