function [BestRoom,PossibleRooms]=AddClass(coursepop,t,s,tl) %Excel File with current course schedule data [NumData,TxtData,RawData]=xlsread('schedule.xlsx','A Term'); %List of total rooms Total_Rooms={'AFTURF';'AHB06';'AHB17';'AHB30';'AK108';'AK113';'AK116'; 'AK120D';'AK219';'AK227';'AK232';'AK233';'AK317';'DHB13';'FL222'; 'FL311';'FL320';'FLPH-LWR';'FLPH-UPR';'GH007';'GH012';'GH109';'GH110'; 'GH116';'GH205';'GP1002';'GP2233';'GP4101';'GP4104';'GH206';'GH207'; 'GH212';'GH216';'GH227';'GH306';'GH307';'HL114';'HL116';'HL154'; 'HL202';'HL218';'HL230';'KH111';'KH115';'KH116';'KH202';'KH203'; 'KH204';'KH207';'OH107';'OH114';'OH117';'OH126';'OH208';'OH211'; 'OH214';'OH218';'OH223';'SH003';'SH106';'SH202';'SH203';'SH304'; 'SH306';'SH308';'SH309';'SL011';'SL104';'SL105';'SL115';'SL123'; 'SL226';'SL305';'SL402';'SL406';'SL407';'SL411';'SLGH';'WB105'; 'WB226';'WB228';'WB229';'WB323'}; %List of total times Total_Times={'8';'9';'10';'11';'12';'13';'14';'15';'16';'17';'18';'19'; '20';'21';'22'}; %List of total days Total_Days={'mon';'tue';'wed';'thu';'fri'}; %List of total schedules Total_Schedules={'mon,tue,wed,thu,fri';'mon,tue,thu,fri';'mon,tue,wed,thu'; 'mon,thu,fri';'mon,wed,fri';'mon,tue,fri';'mon,tue,thu';'mon,fri'; 'mon,thu';'mon,wed';'thu,fri';'tue,fri';'tue,thu';'tue,wed';'wed,fri'; 'wed,thu';'mon';'tue';'wed';'thu';'fri'}; %List of time/day combinations (indices) for each section and for each day in %sections' schedule (some entries may be NaN which will occur when section %is not held on all five days) TimeDay1=NumData(:,26); TimeDay2=NumData(:,28); TimeDay3=NumData(:,30); TimeDay4=NumData(:,32); TimeDay5=NumData(:,34); %List of rooms (indices) for each section (combination of building code and room %number) RoomCombo=NumData(:,44); %List of start times (indices) for each section StartTimes=NumData(:,37); %List of end times (indices) for each section EndTimes=NumData(:,40); %List of duration times for each section TimeLength=EndTimes-StartTimes; %List of room capacities for each room RoomCap=[99;30;50;40;20;2;202;24;86;50;30;70;32;20;24;38;65;107;196;12;30;24;24;1; 15;20;1;4;6;80;30;20;90;12;10;16;35;95;35;35;90;40;10;26;70;25;25;25;40;205; 20;1;35;26;26;20;35;42;50;40;40;28;35;30;54;48;25;76;54;219;27;14;60;60;48;35; 60;12;16;14;20;85;36]; %List of course populations for each section CoursePop=NumData(:,11); %Total number of course sections in dataset (total number of rows in %spreadsheet) NTotalSections=length(RawData)-1; %Total number of days NTotalDays=length(Total_Days); %Total number of rooms NTotalRooms=length(Total_Rooms); %Total number of times NTotalTimes=length(Total_Times); %Total number of schedules NTotalSchedules=length(Total_Schedules); %OCCUPATION MATRIX %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %The Occupatiion matrix shows how many sections are being held in a room at %a certain time and day %Each counts courses that are held in a certain room during each time/day %combination column in Excel Occupation=zeros(NTotalRooms,NTotalDays*NTotalTimes); for i=1:NTotalSections if RoomCombo(i,1)>0 && TimeDay1(i,1)>0 for tlength=1:TimeLength(i) Occupation(RoomCombo(i,1),TimeDay1(i,1)+5*(tlength-1))=Occupation(RoomCombo(i,1),TimeDay1(i,1)+5*(tlength-1))+1; end end end for i=1:NTotalSections if RoomCombo(i,1)>0 && TimeDay2(i,1)>0 for tlength=1:TimeLength(i) Occupation(RoomCombo(i,1),TimeDay2(i,1)+5*(tlength-1))=Occupation(RoomCombo(i,1),TimeDay2(i,1)+5*(tlength-1))+1; end end end for i=1:NTotalSections if RoomCombo(i,1)>0 && TimeDay3(i,1)>0 for tlength=1:TimeLength(i) Occupation(RoomCombo(i,1),TimeDay3(i,1)+5*(tlength-1))=Occupation(RoomCombo(i,1),TimeDay3(i,1)+5*(tlength-1))+1; end end end for i=1:NTotalSections if RoomCombo(i,1)>0 && TimeDay4(i,1)>0 for tlength=1:TimeLength(i) Occupation(RoomCombo(i,1),TimeDay4(i,1)+5*(tlength-1))=Occupation(RoomCombo(i,1),TimeDay4(i,1)+5*(tlength-1))+1; end end end for i=1:NTotalSections if RoomCombo(i,1)>0 && TimeDay5(i,1)>0 for tlength=1:TimeLength(i) Occupation(RoomCombo(i,1),TimeDay5(i,1)+5*(tlength-1))=Occupation(RoomCombo(i,1),TimeDay5(i,1)+5*(tlength-1))+1; end end end %Multiple sections of a large course are often held in the same room and at %the same time. Occupation_Min shows if there is at least 1 course or 0 %courses in a room at any given time and day Occupation_Min=min(Occupation,1); %Occupation_Pop shows the number of students in a room at any given time %and day by adding the course populations of each section in a certain room %%Each counts course populations that are held in a certain room during each time/day %combination column in Excel Occupation_Pop=zeros(NTotalRooms,NTotalDays*NTotalTimes); for i=1:NTotalSections if RoomCombo(i,1)>0 && TimeDay1(i,1)>0 for tlength=1:TimeLength(i) Occupation_Pop(RoomCombo(i,1),TimeDay1(i,1)+5*(tlength-1))=Occupation_Pop(RoomCombo(i,1),TimeDay1(i,1)+5*(tlength-1))+NumData(i,11); end end end for i=1:NTotalSections if RoomCombo(i,1)>0 && TimeDay2(i,1)>0 for tlength=1:TimeLength(i) Occupation_Pop(RoomCombo(i,1),TimeDay2(i,1)+5*(tlength-1))=Occupation_Pop(RoomCombo(i,1),TimeDay2(i,1)+5*(tlength-1))+NumData(i,11); end end end for i=1:NTotalSections if RoomCombo(i,1)>0 && TimeDay3(i,1)>0 for tlength=1:TimeLength(i) Occupation_Pop(RoomCombo(i,1),TimeDay3(i,1)+5*(tlength-1))=Occupation_Pop(RoomCombo(i,1),TimeDay3(i,1)+5*(tlength-1))+NumData(i,11); end end end for i=1:NTotalSections if RoomCombo(i,1)>0 && TimeDay4(i,1)>0 for tlength=1:TimeLength(i) Occupation_Pop(RoomCombo(i,1),TimeDay4(i,1)+5*(tlength-1))=Occupation_Pop(RoomCombo(i,1),TimeDay4(i,1)+5*(tlength-1))+NumData(i,11); end end end for i=1:NTotalSections if RoomCombo(i,1)>0 && TimeDay5(i,1)>0 for tlength=1:TimeLength(i) Occupation_Pop(RoomCombo(i,1),TimeDay5(i,1)+5*(tlength-1))=Occupation_Pop(RoomCombo(i,1),TimeDay5(i,1)+5*(tlength-1))+NumData(i,11); end end end %Creates vector of initial efficiencies for scheudle Efficiency0=zeros(NTotalRooms*NTotalDays*NTotalTimes,1); for i=1:NTotalSections if RoomCombo(i)>0 && TimeDay1(i)>0 Efficiency0(i,1)=CoursePop(i)/RoomCap(RoomCombo(i)); end end %Sets efficiencies exceeding 1 to 0 for perc=1:length(Efficiency0) if Efficiency0(perc,1)>1 Efficiency0(perc,1)=0; end end %Total initial efficiency is the sum of each initial efficiency in vector %above Initial_Efficiency=sum(Efficiency0); %Total final effiency for optimized schedule set to 0 before optimization Final_Efficiency=0; %Happiness Coefficient puts weight on efficiencies in order to define %preferences and other room/time restrictions Happiness=ones(NTotalSections*NTotalRooms,1); %Courses that must be held in certain rooms are given 1.5 for those rooms %and 0 otherwise %Aerospace classes must be held near wind tunnel FindDept=find(strcmp(TxtData(2:end,3),'AS')); FindRoom=[find(strcmp(Total_Rooms,'HL114'));find(strcmp(Total_Rooms,'HL116'));find(strcmp(Total_Rooms,'HL202'))]; for d=1:length(FindDept) Happiness((FindDept(d)-1)*NTotalRooms+1:FindDept(d)*NTotalRooms)=0; for r=1:length(FindRoom) Happiness((FindDept(d)-1)*NTotalRooms+FindRoom(r))=1.5; end end %Military leadership course must be held in Daniels Hall FindDept=find(strcmp(TxtData(2:end,3),'ML')); FindRoom=find(strcmp(Total_Rooms,'DHB13')); for d=1:length(FindDept) Happiness((FindDept(d)-1)*NTotalRooms+1:FindDept(d)*NTotalRooms)=0; for r=1:length(FindRoom) Happiness((FindDept(d)-1)*NTotalRooms+FindRoom(r))=1.5; end end %Music courses must be held in Alden Hall FindDept=find(strcmp(TxtData(2:end,3),'MU')); FindRoom=[find(strcmp(Total_Rooms,'AHB06'));find(strcmp(Total_Rooms,'AHB17'));find(strcmp(Total_Rooms,'AHB30'))]; for d=1:length(FindDept) Happiness((FindDept(d)-1)*NTotalRooms+1:FindDept(d)*NTotalRooms)=0; for r=1:length(FindRoom) Happiness((FindDept(d)-1)*NTotalRooms+FindRoom(r))=1.5; end end %Courses associated with certain department buildings are given 1.5 for %those buildings and 1 otherwise %Math courses are preferred to be held in Stratton Hall FindDept=find(strcmp(TxtData(2:end,3),'MA')); FindRoom=[find(strcmp(Total_Rooms,'SH106'));find(strcmp(Total_Rooms,'SH202'));find(strcmp(Total_Rooms,'SH203'));find(strcmp(Total_Rooms,'SH304'));find(strcmp(Total_Rooms,'SH306'));find(strcmp(Total_Rooms,'SH308'));find(strcmp(Total_Rooms,'SH309'))]; for d=1:length(FindDept) for r=1:length(FindRoom) Happiness((FindDept(d)-1)*NTotalRooms+FindRoom(r))=1.5; end end %Physics courses are preferred to be held in Olin Hall FindDept=find(strcmp(TxtData(2:end,3),'PH')); FindRoom=[find(strcmp(Total_Rooms,'OH107'));find(strcmp(Total_Rooms,'OH126'));find(strcmp(Total_Rooms,'OH214'));find(strcmp(Total_Rooms,'OH218'));find(strcmp(Total_Rooms,'OH223'))]; for d=1:length(FindDept) for r=1:length(FindRoom) Happiness((FindDept(d)-1)*NTotalRooms+FindRoom(r))=1.5; end end %ECE and Robotics courses are preferred to be held in Atwater-Kent FindDept=[find(strcmp(TxtData(2:end,3),'ECE'));find(strcmp(TxtData(2:end,3),'RBE'))]; FindRoom=[find(strcmp(Total_Rooms,'AK116'));find(strcmp(Total_Rooms,'AK219'));find(strcmp(Total_Rooms,'AK232'));find(strcmp(Total_Rooms,'AK233'))]; for d=1:length(FindDept) for r=1:length(FindRoom) Happiness((FindDept(d)-1)*NTotalRooms+FindRoom(r))=1.5; end end %IMGD courses are preferred to be held in Fuller Labs FindDept=find(strcmp(TxtData(2:end,3),'IMGD')); FindRoom=[find(strcmp(Total_Rooms,'FL222'));find(strcmp(Total_Rooms,'FL311'));find(strcmp(Total_Rooms,'FL320'));find(strcmp(Total_Rooms,'FLPH-LWR'));find(strcmp(Total_Rooms,'FLPH-UPR'))]; for d=1:length(FindDept) for r=1:length(FindRoom) Happiness((FindDept(d)-1)*NTotalRooms+FindRoom(r))=1.5; end end %Defines order of optimization for each block for s=1:NTotalSchedules for t=0:NTotalTimes for tl=1:max(TimeLength) %Indexes columns in Occupation matrix for each specified schedule and time if s==1 Occupation_Indexing=[t*NTotalDays+1,t*NTotalDays+2,t*NTotalDays+3,t*NTotalDays+4,t*NTotalDays+5]; elseif s==2 Occupation_Indexing=[t*NTotalDays+1,t*NTotalDays+2,t*NTotalDays+4,t*NTotalDays+5]; elseif s==3 Occupation_Indexing=[t*NTotalDays+1,t*NTotalDays+2,t*NTotalDays+3,t*NTotalDays+4]; elseif s==4 Occupation_Indexing=[t*NTotalDays+1,t*NTotalDays+4,t*NTotalDays+5]; elseif s==5 Occupation_Indexing=[t*NTotalDays+1,t*NTotalDays+3,t*NTotalDays+5]; elseif s==6 Occupation_Indexing=[t*NTotalDays+1,t*NTotalDays+2,t*NTotalDays+5]; elseif s==7 Occupation_Indexing=[t*NTotalDays+1,t*NTotalDays+2,t*NTotalDays+4]; elseif s==8 Occupation_Indexing=[t*NTotalDays+1,t*NTotalDays+5]; elseif s==9 Occupation_Indexing=[t*NTotalDays+1,t*NTotalDays+4]; elseif s==10 Occupation_Indexing=[t*NTotalDays+1,t*NTotalDays+3]; elseif s==11 Occupation_Indexing=[t*NTotalDays+4,t*NTotalDays+5]; elseif s==12 Occupation_Indexing=[t*NTotalDays+2,t*NTotalDays+5]; elseif s==13 Occupation_Indexing=[t*NTotalDays+2,t*NTotalDays+4]; elseif s==14 Occupation_Indexing=[t*NTotalDays+2,t*NTotalDays+3]; elseif s==15 Occupation_Indexing=[t*NTotalDays+3,t*NTotalDays+5]; elseif s==16 Occupation_Indexing=[t*NTotalDays+3,t*NTotalDays+4]; elseif s==17 Occupation_Indexing=t*NTotalDays+1; elseif s==18 Occupation_Indexing=t*NTotalDays+2; elseif s==19 Occupation_Indexing=t*NTotalDays+3; elseif s==20 Occupation_Indexing=t*NTotalDays+4; elseif s==21 Occupation_Indexing=t*NTotalDays+5; end NIndex=length(Occupation_Indexing); %Occupation_Efficiency shows the effiency for each room during each hour %and day Occupation_Efficiency=zeros(NTotalRooms,NTotalDays*NTotalTimes); for r=1:NTotalRooms Occupation_Efficiency(r,:)=Occupation_Pop(r,:)/RoomCap(r); end %SubSections lists rows of courses with schedule s, time t, and time length %tl SubSections=[]; row=1; for i=1:NTotalSections if s==NumData(i,19) && t==NumData(i,37) && tl==TimeLength(i) && RoomCombo(i)>0 SubSections(row,1)=i; row=row+1; end end NSubSections=length(SubSections); %If there are no sections for the given s, t, and tl, then continue on to %next block if isempty(SubSections)==1; continue else %Occupation matrix for courses in specified block Sub_Occupation=zeros(NTotalRooms,NTotalDays*NTotalTimes); for i=1:NSubSections if RoomCombo(SubSections(i),1)>0 && TimeDay1(SubSections(i),1)>0 for index=1:NIndex Sub_Occupation(RoomCombo(SubSections(i)),Occupation_Indexing(index))=Sub_Occupation(RoomCombo(SubSections(i)),Occupation_Indexing(index))+1; end end end %MODEL %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Sums entries in each row of occupation matrix CourseSum=zeros(NTotalRooms,1); for r=1:NTotalRooms for index=1:NIndex for tlength=1:tl PartofSum=Occupation_Min(r,Occupation_Indexing(index)+5*(tlength-1)); CourseSum(r,1)=CourseSum(r,1)+PartofSum; end end end %Sums entries in each row of sub-occupation matrix SubCourseSum=zeros(NTotalRooms,1); for r=1:NTotalRooms for index=1:NIndex SubPartofSum=Sub_Occupation(r,Occupation_Indexing(index)); SubCourseSum(r,1)=SubCourseSum(r,1)+SubPartofSum; end end %Lists avaialable and occupied rooms %Available room when sum of row in occupation matrix = 0 %Occupied room when sum of row in sub-occupation matrix ~=0 Occupied_Rooms=[]; Available_Rooms=[]; for r=1:NTotalRooms if CourseSum(r,1)==0 AvailRoom(1,1)=r; Available_Rooms=[Available_Rooms;AvailRoom]; elseif SubCourseSum(r,1)>0 OccRoom(1,1)=r; Occupied_Rooms=[Occupied_Rooms;OccRoom]; end end RoomList=[Occupied_Rooms;Available_Rooms]; %Total number of occupied courses in specified schedule and time = Total %number of assigned courses NOccupied_Rooms=length(Occupied_Rooms); %Total number of available courses in specified schedule and time = Total %number of dummy courses NAvailable_Rooms=length(Available_Rooms); if isempty(Occupied_Rooms)==1 CoursePopList=[]; elseif isempty(Occupied_Rooms)==0 for r=1:NOccupied_Rooms CoursePopList(r,1)=Occupation_Pop(Occupied_Rooms(r),Occupation_Indexing(1,1)); end end %ADD COURSE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% while coursepop~=0 %1) CHECK AVAILABLE ROOMS %List of capacities for each available room at specified schedule and time for row=1:NAvailable_Rooms PossibleRooms_CapA(row,1)=RoomCap(Available_Rooms(row)); end %List of cost values for population of course being added divided by each %available room capacity (measures efficiency) Efficiency_NewtoAvail=coursepop./PossibleRooms_CapA; for perc=1:length(Efficiency_NewtoAvail) if Efficiency_NewtoAvail(perc,1)>1 Efficiency_NewtoAvail(perc,1)=0; end end %Output best room in regards to efficiency BestRoom=Total_Rooms(Available_Rooms(find(Efficiency_NewtoAvail==max(Efficiency_NewtoAvail)))); %Output other possible rooms PossibleRooms=Total_Rooms(Available_Rooms(find(Efficiency_NewtoAvail~=0))); coursepop=0; %2) CHECK OCCUPIED ROOMS %List of capacities for each occupied room at specified schedule and time if isempty(PossibleRooms_NewtoAvail)==1 for row=1:NOccupied_Rooms PossibleRooms_CapO(row,1)=RoomCap(Occupied_Rooms(row)); end %List of cost values for population of course being added divided by each %occupied room capacity (measures efficiency) Efficiency_NewtoOcc=coursepop./PossibleRooms_CapO; for perc=1:length(Efficiency_NewtoOcc) if Efficiency_NewtoOcc(perc,1)>1 Efficiency_NewtoOcc(perc,1)=0; end end %List of cost values for population of course already assigned divided by each %corresponding room capacity (measures efficiency) Efficiency_Occ=CoursePopList./PossibleRooms_CapO; for perc=1:length(Efficiency_Occ) if Efficiency_Occ(perc,1)>1 Efficiency_Occ(perc,1)=0; end end Efficiency_Diff=Efficiency_NewtoOcc-Efficiency_Occ; if max(Efficiency_Diff)>0 BestRoom=Total_Rooms(Occupied_Rooms(find(Efficiency_Diff==max(Efficiency_Diff)))); coursepop=CoursePopList(find(Efficiency_Diff==max(Efficiency_Diff))); else BestRoom=[]; end %UPDATE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Update occupation matrices OldCourseSchedule=find(Initial_Schedule); NewCourseSchedule=find(New_Schedule); for row=1:NOccupied_Rooms if OldCourseSchedule(row)~=NewCourseSchedule(row) OldRoomNum=RoomList(OldCourseSchedule(row)-(row-1)*(NOccupied_Rooms+NAvailable_Rooms)); NewRoomNum=RoomList(NewCourseSchedule(row)-(row-1)*(NOccupied_Rooms+NAvailable_Rooms)); for index=1:NIndex Occupation_Min(OldRoomNum,Occupation_Indexing(index))=Occupation_Min(OldRoomNum,Occupation_Indexing(index))-1; Occupation_Min(NewRoomNum,Occupation_Indexing(index))=Occupation_Min(NewRoomNum,Occupation_Indexing(index))+1; Occupation_Pop(OldRoomNum,Occupation_Indexing(index))=Occupation_Pop(OldRoomNum,Occupation_Indexing(index))-CoursePopList(row); Occupation_Pop(NewRoomNum,Occupation_Indexing(index))=Occupation_Pop(NewRoomNum,Occupation_Indexing(index))+CoursePopList(row); end end end else continue end %ends if statement for checking occupied rooms if ano available rooms end %ends while loop, which means last course being added was assigned to an available room