我目前正在从事我的毕业项目,该项目正在使用遗传算法解决大学课程排课问题。 在这个项目中,我使用了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;
}
此功能可以处理小型数据集的第一个和第二个软约束,但是对于中型和大型数据集,此功能花费的时间太长,这也是我认为是由于深度复制所致。