Edge Minimizing the Student Conflict Graph
EEdge Minimizing the Student Conflict Graph
J.S. Friedman ∗ Abstract
In many schools, courses are given in sections. Prior to timetabling students need to beassigned to individual sections. We give a hybrid approximation sectioning algorithm that mini-mizes the number of edges (potential conflicts) in the student conflict graph (SCG). We start witha greedy algorithm to obtain a starting solution and then continue with a constraint programmingbased algorithm (CP-SAT) that reduces the number of edges. We apply the sectioning algorithmto a highly constrained timetabling model which we specify.
Academic timetabling is the task of scheduling courses to specific times in such a way that there areno conflicts. Most of the models considered in the literature assume that this conflict informationis already known. However in many real life timetabling problems, courses are taught in multiplesections and until a student is assigned to a specific section of a course, the conflict information isnot known.M.W. Carter [Car00] sums it up nicely “When courses are offered in multiple sections as theyare at Waterloo, it creates a timetabling paradox. Students request a course, but timetabling assignsdays and times to course sections. We cannot assign times to sections until we know which studentsare in each section. But we cannot assign students to sections until we know when the sections aretimetabled!” We call this paradox the student sectioning problem.One solution is to try to solve both sectioning and timetabling problems simultaneously. Whenformulating 0-1 integer programs (IP) to model this situation, the resulting IP is huge and quicklybecome intractable: the search space is very large .We briefly define two graphs of interest and give more details below. Suppose we have n students and each has to enroll in a set of courses. Suppose each course can be split into differentsections so when a student enrolls in a course they actually enroll in a specific section. Considerthe course conflict graph (CCG) where vertices are courses and edges signify at least one studentmust take the two courses incident with that edge. Next split each course of the CCG into sections.The student conflict graph (SCG) is the graph where the vertices are the sections. A feasible studentsectioning would induce edges in the SCG, where an edge connects two sections if a student isenrolled in both sections, or if a professor teaches the two sections, or if the two sections need thesame room (specialty lab course). If one assigns students to sections in a random way the number ∗ The views expressed in this article are the author’s own and not those of the U.S. Merchant Marine Academy, theMaritime Administration, the Department of Transportation, or the United States government. According to our experiments, solving the combined IP with the Gurobi solver seems to take two orders of magnitudemore time than separating out the sectioning first. a r X i v : . [ c s . A I] F e b f edges would be larger than necessary, and the chromatic number may be too high and/or it maybe very difficult/impossible to find a feasible timetable.In [Sch19] D. Schindl makes important progress on the student sectioning problem. In [Sch19]an optimal sectioning of students is given in the special case where 1) all students have the samerequired list of courses, and 2) the courses are split into balanced sections. Schindl proves that a typeof sectioning called regular sectioning creates a minimal-edged SCG. Furthermore, the sectioning canbe done quickly as it is not NP-hard. Though [Sch19] deals with a special case, it hinted to us thatstudying the SCG more systematically, investing more computational time upfront, could maketimetabling much easier when sectioning is involved. Sectioning deserves much more attention inthe literature.In [LD86] Laporte and Desroches considered the student sectioning problem in the situationwhere a complete timetable was already published. They first group students with identicalschedules and merge them into a k − student, and then try to optimally schedule them into sections,ignoring room capacities. Next they attempt to balance sections and respect room capacities, usinglocal tree search techniques.In [Car00] M.W. Carter also realized that the SCG is crucial to finding a feasible timetable, thoughhe calls it the conflict matrix . He defines a metric on the set of students that measures whether twostudents have similar course requests, and assigns students to sections so that two students whoare near each other are likely to be assigned to the same sections. Once this assignment is done atimetable is computed, and then students are reassigned if necessary to different sections. Cartercalls this sectioning homogeneous sectioning and shows via experiment that it reduces the numberof conflict edges by approximately twenty percent.In Müller et al. [MMR06, MM10] they study the student sectioning problem at a large university.They start with an initial sectioning that based on Carter’s homogeneous sectioning. Then a localsearch algorithm is used to improve on the initial sectioning using the following two moves: • Two students enrolled in the same course swap all of their class assignments. • A student is re-enrolled into classes associated with a course such that the number of conflictsinvolving that student is minimized.In [MMR06, MM10] they do not have all of the student request information at the time of timetableconstruction, so later on they do additional sectioning.In [Sel88] S.M. Selim approaches the student sectioning problem using a vertex splitting scheme.Before courses are split into sections one can form the course conflict graph (CCG). The chromaticnumber of this graph can exceed the number of available periods, and Selim gives careful conditionson how splitting course vertices into sections, so that the CCG becomes the SCG, can reduce thechromatic number of the final SCG. The real-life problem that Selim solves only has 12 differentcourses and each student takes three courses. It is not clear if his method would scale up to ourmodel.The purpose of our paper is to generalize the work of [Sch19] on the student conflict graph (SCG)to the case where students all have a list of required courses, but they can differ from one student tothe next; and the sections do not have to be balanced. The resulting problem is NP-hard and hencewe can not hope to find an optimal solution as Schindl does for his case. We give an approximationalgorithm which produces a sectioning that gives an approximate minimal-edged SCG. We define It is possible to relate our problem to a certain partitioning problem which is known to be NP-Hard. More details willfollow in a future publication.
Sec 216ECEM400enrl=18room=47 Sec 109ECNA401enrl=18room=58 Sec 240ECME470enrl=18room=46 Sec 315ECEE400enrl=25room=54 T Sec 115ELEC402enrl=56room=28 Sec 109ECNA401enrl=18room=60 Sec 303ECME450enrl=18room=50 Sec 0COMM999enrl=707room=0 W Sec 115ELEC402enrl=56room=28 Sec 303ECME450enrl=18room=55 Sec 316ECEE400Lenrl=25room=66 Sec 316ECEE400Lenrl=25room=66 R Sec 304ECME450Lenrl=18room=68 Sec 304ECME450Lenrl=18room=68 Sec 304ECME450Lenrl=18room=68 Sec 115ELEC402enrl=56room=33 Sec 315ECEE400enrl=25room=55 Sec 217ECEM400Lenrl=18room=56 Sec 217ECEM400Lenrl=18room=56 F Sec 115ELEC402enrl=56room=36 Sec 109ECNA401enrl=18room=52 Sec 303ECME450enrl=18room=55 Sec 240ECME470enrl=18room=50 Sec 241ECME470Lenrl=18room=40 Sec 241ECME470Lenrl=18room=40 Sec 241ECME470Lenrl=18room=40Group 1EA.114, Size of group 14, num of periods 26, courses required , ECEM400L, ECME450, ECEM400, ECME470,ECEE400, ECEE400L, ECNA401, ELEC402, COMM999, ECME450L, ECME470L ewline5
Sec 218ECEM400enrl=18room=59 Sec 242ECME470enrl=18room=60 Sec 110ECNA401enrl=18room=48 T Sec 115ELEC402enrl=56room=28 Sec 242ECME470enrl=18room=49 Sec 0COMM999enrl=707room=0 Sec 110ECNA401enrl=18room=47 W Sec 115ELEC402enrl=56room=28 Sec 305ECME450enrl=18room=57 Sec 219ECEM400Lenrl=18room=56 Sec 219ECEM400Lenrl=18room=56 Sec 306ECME450Lenrl=18room=68 Sec 306ECME450Lenrl=18room=68 Sec 306ECME450Lenrl=18room=68 R Sec 314ECEE400Lenrl=25room=66 Sec 314ECEE400Lenrl=25room=66 Sec 115ELEC402enrl=56room=33 Sec 305ECME450enrl=18room=51 Sec 313ECEE400enrl=25room=61 Sec 110ECNA401enrl=18room=55 F Sec 115ELEC402enrl=56room=36 Sec 243ECME470Lenrl=18room=40 Sec 243ECME470Lenrl=18room=40 Sec 243ECME470Lenrl=18room=40 Sec 313ECEE400enrl=25room=46 Sec 305ECME450enrl=18room=47Group 1EA.115, Size of group 18, num of periods 26, courses required , ECEM400L, ECME450, ECEM400, ECME470,ECEE400, ECEE400L, ECNA401, ELEC402, COMM999, ECME450L, ECME470L ewline6
Sec 308ECME450Lenrl=18room=68 Sec 308ECME450Lenrl=18room=68 Sec 308ECME450Lenrl=18room=68 Sec 244ECME470enrl=18room=52 Sec 111ECNA401enrl=18room=60 Sec 220ECEM400enrl=18room=46 T Sec 115ELEC402enrl=56room=28 Sec 221ECEM400Lenrl=18room=56 Sec 221ECEM400Lenrl=18room=56 Sec 0COMM999enrl=707room=0 Sec 307ECME450enrl=18room=61 W Sec 115ELEC402enrl=56room=28 Sec 245ECME470Lenrl=18room=40 Sec 245ECME470Lenrl=18room=40 Sec 245ECME470Lenrl=18room=40 Sec 244ECME470enrl=18room=59 Sec 111ECNA401enrl=18room=58 R Sec 314ECEE400Lenrl=25room=66 Sec 314ECEE400Lenrl=25room=66 Sec 115ELEC402enrl=56room=33 Sec 313ECEE400enrl=25room=61 Sec 307ECME450enrl=18room=59 F Sec 115ELEC402enrl=56room=36 Sec 313ECEE400enrl=25room=46 Sec 111ECNA401enrl=18room=58 Sec 307ECME450enrl=18room=52Group 1EA.116, Size of group 7, num of periods 26, courses required , ECEM400L, ECME450, ECEM400, ECME470,ECEE400, ECEE400L, ECNA401, ELEC402, COMM999, ECME450L, ECME470L ewline7
Sec 308ECME450Lenrl=18room=68 Sec 308ECME450Lenrl=18room=68 Sec 308ECME450Lenrl=18room=68 Sec 160NASC400enrl=18room=62 Sec 244ECME470enrl=18room=52 Sec 111ECNA401enrl=18room=60 Sec 220ECEM400enrl=18room=46 T Sec 221ECEM400Lenrl=18room=56 Sec 221ECEM400Lenrl=18room=56 Sec 282EMEM415enrl=18room=56 Sec 0COMM999enrl=707room=0 Sec 307ECME450enrl=18room=61 W Sec 98ECES401enrl=16room=49 Sec 245ECME470Lenrl=18room=40 Sec 245ECME470Lenrl=18room=40 Sec 245ECME470Lenrl=18room=40 Sec 244ECME470enrl=18room=59 Sec 111ECNA401enrl=18room=58 Sec 282EMEM415enrl=18room=56 R Sec 98ECES401enrl=16room=58 Sec 160NASC400enrl=18room=62 Sec 282EMEM415enrl=18room=56 Sec 281EMEM415Lenrl=18room=56 Sec 307ECME450enrl=18room=59 F Sec 103ECME440Lenrl=18room=18 Sec 103ECME440Lenrl=18room=18 Sec 103ECME440Lenrl=18room=18 Sec 103ECME440Lenrl=18room=18 Sec 111ECNA401enrl=18room=58 Sec 307ECME450enrl=18room=52Group 1MA.119, Size of group 11, num of periods 30, courses required , ECEM400L, ECME450, ECEM400, ECME470,ECES401, NASC400, EMEM415L, ECNA401, EMEM415, COMM999, ECME450L, ECME440L, ECME470L ewline10
Figure 1:
In three of the schedules (1,2,3) the students have the same required courses but they are in mostlydifferent sections. In the schedule (4) students from a different major share some sections with (3). This allowsfor balanced sections and a minimal amount of teaching staff.
See Figure 1 for an example of the type of timetabling problem we solve. As one can see, ourmodel allows a very dense student schedule and all courses are required. This model is applicableto any school that wants to maximize student learning in a minimal amount of time. In fact, thisis the model used at the U.S. Merchant Marine Academy where students essentially earn threedegrees in four years, spending one of those years at sea. They receive an officer commission inthe U.S. Navy, a U.S. Coast Guard license, and a rigorous B.S. degree, all while earning upwards of160 credits in certain majors. Clearly this model is not for very large universities, but for schoolswho wish to become more efficient it might be advantageous.Ultimately the purpose of student sectioning is to construct a timetable. Our model is notusually studied in the literature. Though small compared to large university models, our is meantfor less students but with really packed schedules. We split the week into equal sized periods, forexample seven one-hour periods per day, 5 days per week. The model includes lectures (3 or 4periods a week, one meeting per day) and extended lectures (multiple periods in a row). Takingone look at Figure 2 shows that predefined set course times would extend the day in our model,3s our model can pack in more courses more efficiently. What makes our model challengingare the numerous extended lectures and the dense amount of periods used. In the timetablingprocess it is very difficult to move an extended section as they anchor the timetable and conflict withother sections that do not have the same footprint. The problem is highly constrained (sometimesover-constrained). The model that we propose has the potential to utilize time and space moreefficiently, especially if the majors have significant overlap and there are many required courses.Our model is student centric, and students are guaranteed a spot in all of their courses.We have created instances of various difficulty of our models and posted the source code forour work, as well as a solved timetable on (https://github.com/mathprofessor/timetable) . We consider the following model for student sectioning and timetabling. Let G denote the setof students. We partition G into major-groups M where (cid:83) m ∈ M m = G. Let C denote the set of courses , and S the set of sections. For each course c ∈ C we have a set of sections S c , where the S c partition S. For example, Calc1 would represent a course, and Calc1.01, Calc1.02,... would be thecorresponding sections. When a student enrolls in a course they select exactly one section. Eachstudent g in a fixed major-group m is required to enroll in a set of courses C m . More precisely, eachstudent must enroll in a particular section of each course in C m . Some sections are tied togetherin the parent/child relationship like lectures and labs. Section s is the unique parent of s ifenrollment in s implies enrollment in s ; conversely s is a child of s , and the set of sectionsconsisting of a parent and all children is a family . Our model precludes grandchildren and to limitcomplexity of the model we insist that all members of a family have the same capacity. Notethat we consider parent and child (and their corresponding courses) as separate entities as theygenerally have different staffing and room requirements.The major-group is not a standard concept so we illustrate with an example. consider a smallcollege or a large high school that offers 5 majors: Arts, Math, Engineering, Computers, andBiology. Suppose there are 4 class years: Freshman, Sophomore, Junior, Senior, and each class yearis split into Honors or Standard. This would correspond to (5)(4)(2) = 40 major-groups. Eachstudent in a major-group has identical course requirements but they can enroll in different sections.There would be courses common to distinct major-groups (core courses that everyone takes). Inaddition, there could be major-groups of students who failed courses and must retake them andadvanced students with unique course requirements. So in practice, there could be more than 40major-groups, and it is possible that a major-group could include a single student. In our modelelective choices are not applicable: any student can enroll in a section of any course, in theory theycan have a unique schedule.We partition students G into divisions , D, where (cid:83) d ∈ D d = G, where each student in a division d has an identical section schedule. It follows that each division is subset of a unique major-group.See Figure 2 and Figure 3 for more illustration.Let R denote the set of rooms. We partition R into room-types RT where (cid:83) q ∈ RT q = R. Let P denote the set of professors. For each section s ∈ S we assign (before any sectioning) a professor p = p ( s ) and a room-type q = q ( s ) . In real-life models one would need a satillite-family where a big lecture branches into smaller recitations and labs andthe capacities of the members differ. Our model can easily be extended to include this. Sec 248ECME470enrl=12room=53 Sec 100ECES401enrl=16room=55 Sec 284EMEM415enrl=18room=56 Sec 249ECME470Lenrl=12room=40 Sec 249ECME470Lenrl=12room=40 Sec 249ECME470Lenrl=12room=40 T Sec 202ECME420enrl=24room=57 Sec 248ECME470enrl=12room=52 Sec 113ECNA401enrl=7room=46 Sec 161NASC400enrl=18room=62 Sec 0COMM999enrl=707room=0 Sec 284EMEM415enrl=18room=56 W Sec 283EMEM415Lenrl=18room=56 Sec 284EMEM415enrl=18room=56 Sec 113ECNA401enrl=7room=53 Sec 202ECME420enrl=24room=54 Sec 333ECME431enrl=14room=49 Sec 161NASC400enrl=18room=62 R Sec 104ECME440Lenrl=18room=18 Sec 104ECME440Lenrl=18room=18 Sec 104ECME440Lenrl=18room=18 Sec 104ECME440Lenrl=18room=18 Sec 334ECME431Lenrl=14room=41 Sec 334ECME431Lenrl=14room=41 Sec 334ECME431Lenrl=14room=41 F Sec 100ECES401enrl=16room=58 Sec 113ECNA401enrl=7room=57 Sec 333ECME431enrl=14room=47 Sec 202ECME420enrl=24room=59 Sec 203ECME420Lenrl=24room=41 Sec 203ECME420Lenrl=24room=41 Sec 203ECME420Lenrl=24room=41Group 1MC.1113, Size of group 7, num of periods 32, courses required , ECME431L, ECME431, ECME470, NASC400,ECES401, EMEM415L, ECME420L, ECNA401, EMEM415, COMM999, ECME440L, ECME420, ECME470L ewline14 (a)
Division 1MC.1 7 students
Sec 225ECEM400Lenrl=17room=56 Sec 225ECEM400Lenrl=17room=56 Sec 100ECES401enrl=16room=55 Sec 143MATH320enrl=9room=58 Sec 116ESME400enrl=9room=87 Sec 122HIST300enrl=14room=54 Sec 224ECEM400enrl=17room=49 T Sec 202ECME420enrl=24room=57 Sec 336ECME431Lenrl=15room=41 Sec 336ECME431Lenrl=15room=41 Sec 336ECME431Lenrl=15room=41 Sec 0COMM999enrl=707room=0 Sec 335ECME431enrl=15room=54 Sec 116ESME400enrl=9room=87 W Sec 106ECME440Lenrl=17room=18 Sec 106ECME440Lenrl=17room=18 Sec 106ECME440Lenrl=17room=18 Sec 106ECME440Lenrl=17room=18 Sec 202ECME420enrl=24room=54 Sec 335ECME431enrl=15room=59 R Sec 122HIST300enrl=14room=51 Sec 102ECME410Lenrl=14room=42 Sec 102ECME410Lenrl=14room=42 Sec 102ECME410Lenrl=14room=42 Sec 143MATH320enrl=9room=54 F Sec 100ECES401enrl=16room=58 Sec 143MATH320enrl=9room=50 Sec 122HIST300enrl=14room=57 Sec 202ECME420enrl=24room=59 Sec 203ECME420Lenrl=24room=41 Sec 203ECME420Lenrl=24room=41 Sec 203ECME420Lenrl=24room=41Group 2SC.842, Size of group 9, num of periods 32, courses required , ECEM400L, ESME400, ECME431L, ECME431,ECEM400, ECME440L, ECES401, MATH320, ECME420L, COMM999, HIST300, ECME410L, ECME420 ewline43 (b)
Division 2SC.2 9 students
Figure 2:
Note how the two divisions share sections 100, 202, 203 even though they require a different set ofcourses. The two divisions come from two different major-groups 1MC and 2SC.
Suppose that each major-group m has size | m | and each section s has capacity | s | . The problemwe consider is how to split the required courses into sections so each student of each major-groupcan enroll in a course without violating the capacity of the sections.
For each student g ∈ G, there is a unique major-group m g with g ∈ m g . Let C g = C m denote therequired courses of g. Define the set GC = { ( g, c ) | g ∈ G, c ∈ C g } . For each section s, π ( s ) is thecorresponding course associated to s, that is s ∈ S π ( s ) . Define the set W = { ( g, s ) | g ∈ G, s ∈ π − ( C g ) } . In other words, ( g, s ) ∈ W if s is a section that student g could enroll in. Definition 2.1.
We define a sectioning to be a function f : GC (cid:55)→ W so the following properties aresatisfied:1. If f ( g, c ) = ( g, s ) then s ∈ S c . In this case we say g is assigned to section s.
2. For each s ∈ S, the number of students assigned to s does not exceed | s | .
3. If s is the parent of s then f ( g, π ( s )) = ( g, s ) implies f ( g, π ( s )) = ( g, s ) . Definition 2.2.
Let f be a sectioning. The student conflict graph of f, SCG ( f ) is the graph whosevertices are the sections s ∈ S, and whose edges are given by1. ( s , s ) if there is a professor who teaches both sections s and s ; ( s , s ) if s and s have the same room-type q ( s ) = q ( s ) , and the number of availablerooms in the room-type q ( s ) is exactly one;3. ( s , s ) if there is a student g who is assigned to both sections s and s with respect to thesectioning f. Sec 10NASC100enrl=23room=12 Sec 327ECME105enrl=16room=57 Sec 328ECME105Lenrl=16room=69 Sec 328ECME105Lenrl=16room=69 Sec 328ECME105Lenrl=16room=69 T Sec 3HIST100enrl=30room=48 Sec 8PEA110enrl=25room=85 Sec 190PHYS110enrl=28room=61 Sec 0COMM999enrl=707room=0 Sec 327ECME105enrl=16room=51 Sec 33MATH140enrl=28room=57 W Sec 327ECME105enrl=16room=51 Sec 10NASC100enrl=23room=12 Sec 191PHYS110Lenrl=28room=84 Sec 191PHYS110Lenrl=28room=84 Sec 33MATH140enrl=28room=54 Sec 190PHYS110enrl=28room=48 R Sec 16ECMT111Lenrl=29room=70 Sec 16ECMT111Lenrl=29room=70 Sec 16ECMT111Lenrl=29room=70 Sec 51MLOG120enrl=29room=7 Sec 3HIST100enrl=30room=57 F Sec 54BUSN101enrl=22room=8 Sec 190PHYS110enrl=28room=46 Sec 8PEA110enrl=25room=85 Sec 3HIST100enrl=30room=60 Sec 33MATH140enrl=28room=55Group4EXABC.2112, Sizeofgroup3, numofperiods27, coursesrequired, PHYS110L,PEA110, BUSN101, ECMT111L,ECME105L, MATH140, MLOG120, HIST100, COMM999, PHYS110, ECME105, NASC100 ewline113 (a)
Division 4EX.1 3 students
Sec 329ECME105enrl=16room=60 Sec 330ECME105Lenrl=16room=69 Sec 330ECME105Lenrl=16room=69 Sec 330ECME105Lenrl=16room=69 T Sec 11NASC100enrl=22room=9 Sec 3HIST100enrl=30room=48 Sec 8PEA110enrl=25room=85 Sec 190PHYS110enrl=28room=61 Sec 0COMM999enrl=707room=0 Sec 329ECME105enrl=16room=60 Sec 33MATH140enrl=28room=57 W Sec 191PHYS110Lenrl=28room=84 Sec 191PHYS110Lenrl=28room=84 Sec 11NASC100enrl=22room=12 Sec 33MATH140enrl=28room=54 Sec 190PHYS110enrl=28room=48 R Sec 16ECMT111Lenrl=29room=70 Sec 16ECMT111Lenrl=29room=70 Sec 16ECMT111Lenrl=29room=70 Sec 51MLOG120enrl=29room=7 Sec 3HIST100enrl=30room=57 Sec 329ECME105enrl=16room=58 F Sec 55BUSN101enrl=22room=7 Sec 190PHYS110enrl=28room=46 Sec 8PEA110enrl=25room=85 Sec 3HIST100enrl=30room=60 Sec 33MATH140enrl=28room=55Group4EXABC.2115,Sizeofgroup11,numofperiods27,coursesrequired,PHYS110L,PEA110,BUSN101,ECMT111L,ECME105L, MATH140, MLOG120, HIST100, COMM999, PHYS110, ECME105, NASC100 ewline116 (b)
Division 4EX.2 11 students
Figure 3:
Note how the two divisions are in the same major-group 4EX (they require the same courses) butsome of their sections differ.
Our algorithm is a hybrid of two parts. The first is a greedy algorithm similar in spirit to [Car00],which will give an initial solution far superior to randomly assigning students to sections. Theresults of the first part are passed to an open source constraint solver (CP-SAT) that further improvesthe objective.
Let G be the set of students. We define a distance function on G by d ( g , g ) = | C g (cid:9) C g | , where (cid:9) is the symmetric set difference.6 lgorithm 1: Greedy Sectioning
Result:
Heuristic algorithm to create an approximate edge-minimal SCG.
Initialization:
Create the base SGC: For each s ∈ S add a vertex. Add all edges ( s , s ) whenever the first two items of Definition 2.2 apply.Choose a random student g ∈ G and randomly assign g to sections, S g , consistent withDefinition 2.1. Add edges to the SGC consistent with third item of Definition 2.2.assign g := g ; while While there are still students who need to enroll do Choose an unenrolled student h so d ( h, g ) is minimal.Let S gh be the open sections of S g that h also needs to enroll in;Enroll h in all courses of S gh ; For each course c in C h that is still needed, choose the section s of c so that it will addthe minimal amount of new edges to the SGC, remembering the sections h is enrolledin so far from g . Add the rest of the family corresponding to s if needed.Assign g := h ; end The initial algorithm Greedy Sectioning, above, attempts to assign students to sections byordering the students in a chain and copying the schedule, as much as possible, of previouslyscheduled students who have the most similar schedule.Greedy Sectioning has a runtime that is polynomial in the number of students and sections,and is quite fast.
Our algorithm is very similar to an 0-1 integer program. We model the algorithm using stan-dard constraints from integer and constraint program. OR-Tools CP-SAT converts it to a SATinstance which is solved by the CP-SAT solver [PF19]. We import the starting solution from GreedySectioning as a warm start (more specifically OR-Tools calls it a hint for the value of each variable).There will be three options for the objective of the constraint program. The first tries tominimize the number of edges; the second puts a weight on edges associated with sections whouse contiguous periods (since they are difficult to move in the construction of a timetable); andthe third incorporates a signal from a failed attempt to timetable by adding some weight for tabu assignments that the solver should stay clear of. Initially the third option is unavailable. We haveincluded the Python source code in Appendix A.We define some needed sets to formulate the CP. Let1. W = { ( g, s ) | g ∈ G, s ∈ π − ( C g ) } .
2. GC = { ( g, c ) | g ∈ G, c ∈ C g } .
3. SS = { ( s , s ) ∈ S × S | s < s } .
4. GSS = { ( g, s , s ) ∈ G × SS | ( g, s ) , ( g, s ) ∈ W } .
5. PS = { ( p, s ) ∈ P × S | p teaches section s }
6. PSS = { ( p, s , s ) ∈ P × SS | ( p, s ) , ( p, s ) ∈ PS }
7. FSS = { ( s , s ) ∈ S × S | s (cid:54) = s , s is the parent of s } .
8. FGSS = { ( g, s , s ) ∈ G × S × S | ( s , s ) ∈ FSS , ( g, s ) ∈ W } .
9. RSS = { ( r, s , s ) ∈ R × SS | s and s require the exact same room } Next we define boolean variables1. x g,s for ( g, s ) ∈ W. Here x g,s = 1 iff student g is enrolled in section s. y s,t for ( s, t ) ∈ SS . Here y s,t = 1 iff sections s, t can not be scheduled at the same time.The constraints are given by1. for ( s, t ) ∈ RSS ∪ PSS , y s,t = 1 , (both sections have the same professor or need the sameroom)2. for ( g, c ) ∈ GC , (cid:80) s ∈ S c x g,s = 1 , (choose one section from course c )3. for s ∈ S, (cid:88) g ∈ G ( g,s ) ∈ W x g,s ≤ | s | , (do not exceed capacity of section s )4. for ( g, s , s ) ∈ GSS , x g,s ≤ x g,s , (if s has parent s then if we enroll in s we must enrollin s )5. for ( g, s , s ) ∈ GSS , Boolean_OR ( not ( x g,s ) , not ( x g,s ) , y s ,s ) . This constraint could alsobe written as x g,s + x g,s − ≤ y s ,s if one is using a MIP solver, (if student g is enrolled insections s , s then y s ,s must be one.We have three choices for the objective. We minimize1. Z = (cid:80) ( s,t ) ∈ SS y s,t , here we are minimizing the number of edges in the SCG. Minimizingthis objective makes it easier to find a feasible coloring of the SCG which leads to a feasi-ble timetable. However, in our model we have extended sections which take up 2,3, or 4contiguous periods. The next objective takes this into account.2. For ( s, t ) ∈ SS define a weight w s,t by w s,t = a if s and t are both not extended sections b if exactly one of s and t are extended sections c if s and t are both extended sectionswhere a, b, c are appropriately chosen real numbers. Thus Z = (cid:80) ( s,t ) ∈ SS w s,t y s,t , The rational for this is that extended sections are much harder to move in the construction ofa timetable, and the fewer edges incident with extended sections, the better.8. Sometimes after minimizing the edges of the SCG the timetabling process returns withsections that are in conflict. See Appendix B lines 195–204 for the details in Python. Theseconflicts stem from unfortunate assignments of particular students to particular sections. Weplace these assignments in a tabu list and send it back to the CP-SAT Sectioning algorithmand restart the edge minimization where it left off but with a new objective: Z = (cid:88) ( s,t ) ∈ SS w s,t y s,t + d (cid:88) ( g,s ) ∈ tabu x g,s , where d > is chosen appropriately. This modification will discourage the tabu assignments,and starting the search with a warm start (previous solution, which is still feasible) wouldresult in different sectioning. Once we have an attractive sectioning, or even better an entire collection of them computed inparallel, we solve our timetabling model. Each section s requires a number of periods per ( s ) and it is either extended or not. Extended sections have all meetings contiguous and can not beseparated by the lunch period. Our model has one common section that all students must take.Non-extended sections should have no more than one meeting per day. Sections that are adjacenton the SCG should not be scheduled at the same time, and professors should have one day wherethey do not teach . Room capacity constraints are implicitly defined by specifying the room-typeof each section. Our implementation is a boolean (0-1) constraint program (CP) using Google’s OR-Tools CP-SAT solver, Python interface. Our CP utilizes standard constructs and the interested reader canrefer to Appendix B where the Python code can be read quite easily. In addition the source codeis available on https://github.com/mathprofessor/timetable .Our strategy is to first solve the sectioning problem and construct the SCG. Next each constraintis implemented as a soft constraint with a certain weight in the linear objective. For example,a section clash has weight 1000, while running out of rooms in a certain room-type has weight100. A professor not getting a day off from teaching has less weight as does scheduling two ormore meetings of a non-extended class on the same day. The reason for the soft constraints is ourproblems can be over constrained and the CP should indicate if and how we need to change ourinstance to obtain feasibility. Our goal here is a feasible timetable .We first attempt to timetable only the extended sections and the common section. Once a feasiblesolution is found (usually optimal with respect to our soft constraints) we pass this solution to theCP and attempt to timetable the entire problem.If we can not find a feasible timetable, we might only need a different SCG, and we can sendthe tabu data back to the sectioning program and try again, or try a different SCG. Typically wecan solve these difficult problems in 5–30 minutes. See §5 for more details on our experiments. In our experiments we randomly requested a certain day off. In a real-life timetabling application a more specific approach to rooms is required, but our model is a good approxi-mation. Once a feasible timetable exists one would add other soft constraints and either re-solve the global problem or performinglocal searches by slicing up the periods and allowing certain groups of periods to move while keeping others fixed. Computational setup and benchmarks
Our computational machine has a AMD RYZEN 7 2700X 3.7GHZ CPU with 8 cores, capable of16 threads, with 16GB of ram and 16GB or swap space . We implemented our code using Pythonand used Google’s OR-Tools CP-SAT [PF19]. We invoked the solver with 16 threads, and unlikeMIP solvers, we experienced great speedup by using more threads. We also experimented withthe Gurobi solver, and we found that the free open source CP-SAT solver is more efficient for thesetype of problems: sectioning and timetabling problems of this kind do not have a tight relaxation,and MIP solvers may not be the best choice.Four instances have been created (see https://github.com/mathprofessor/timetable ), Easy,Medium, Medium2, and Hard, with 256, 339, 352, and 372 distinct sections respectively.For each instance we ran the sectioning algorithm for (100,600,1800) seconds, three times, andthen allocated 600 seconds to the timetable CP. Looking at the data below, when running theCP-SAT edge reduction, we can remove roughly 7% of the edges after the greedy algorithm, andlooking at the last three lines, makes it possible to solve the hard instance. CP-SATseconds Instance Size of SCGafter Greedy Size of SCGafter CP-SAT Percent reductionof edges Objective Time to optimalsolution of zero100 easy 2616 2531 3.25 0 38 easy 2619 2561 2.21 0 36 easy 2619 2572 1.79 0 37 medium 3992 3849 3.58 3 medium 3976 3825 3.80 14 medium 3970 3785 4.66 18 medium2 4343 4199 3.32 13 medium2 4319 4183 3.15 0 148 medium2 4355 4194 3.70 16 hard 4885 4683 4.14 238 hard 4825 4689 2.82 32 hard 4830 4663 3.46 53 easy 2619 2541 2.98 0 33 easy 2612 2512 3.83 0 37 easy 2612 2505 4.10 0 37 medium 3993 3771 5.56 1 medium 4036 3667 9.14 2018 medium 3987 3666 8.05 0 90 medium2 4339 4090 5.74 2 medium2 4343 4132 4.86 13 medium2 4390 4114 6.29 5 hard 4827 4583 5.05 52 hard 4831 4596 4.86 8 hard 4815 4565 5.19 10536 easy 2633 2495 5.24 0 35 easy 2619 2501 4.51 0 32 easy 2612 2495 4.48 0 35 medium 3970 3650 8.06 0 119 medium 3992 3647 8.64 24 medium 3997 3653 8.61 0 82 medium2 4356 4119 5.44 7 medium2 4347 4061 6.58 0 130 medium2 4342 4064 6.40 0 167 hard 4847 4530 6.54 22 hard 4844 4482 7.47 15 hard 4844 4461 7.91 0 199
A Sectioning CP-SAT Program def secCP(threads , flist , time ,x_m = None ,y_m = None , tabu1 = None): print(’CP-SAT Sectionize’) (S,R,RT,C,P,G,L,D,T,Lunch ,sd,rd,pd,gd,catalog ,divSizeDict ,divDict) = flist W=set([(g,s) for g in G for s in S if (sd[s].course_num in gd[g].course_num_list)]) The CP-SAT needs a lot of memory. GC = [(g,c) for g in G for c in C if c in gd[g].course_num_list ] SS = [(s1,s2) for s1 in S for s2 in S if s1 < s2] GSS = [(g,s1,s2) for g in G for (s1,s2) in SS if ( (g,s1) in W and (g,s2) in W ) ] PS = [(p,s) for p in P for s in S if s in pd[p].secNums] PSS = [(p,s1,s2) for p in P for (s1,s2) in SS if ( (p,s1) in PS and (p,s2) in PS ) ] labtieSS = [(s1,s2) for s1 in S for s2 in S if sd[s1].labtie != ’’ and sd[s1].labtie ==sd[s2].labtie and sd[s1].iAmParent and s1 != s2 ] GlabtieSS = [(g,s1,s2) for g in G for (s1,s2) in labtieSS if (g,s1) in W model = cp_model.CpModel() x = {(g,s) : model.NewBoolVar(’x%i%i’ % (g,s) ) for (g,s) in W} y = {} for (s,t) in SS: y[s,t] = model.NewBoolVar(’x%i%i’ % (s,t) ) weight1 = {} for (s1,s2) in SS: wei = 1 if sd[s1].isExtended: wei+=3 if sd[s2].isExtended: wei+=3 weight1[s1,s2] = wei if tabu1 != None: model.Minimize( sum(weight1[s,t]*y[s,t] for (s,t) in SS ) + sum(5*x[g,s] for (g,s) intabu1)) else: model.Minimize( sum(weight1[s,t]*y[s,t] for (s,t) in SS ) ) if x_m != None: for (g,s) in W: if (g,s) in x_m.keys(): if x_m[g,s] == 1: model.AddHint(x[g,s],1) for (g,s) in W: if (g,s) not in x_m.keys(): model.AddHint(x[g,s],0) for (s1,s2) in SS: model.AddHint(y[s1,s2], y_m[s1,s2]) rtCount = {} for r in R: if rd[r].roomtype in rtCount: rtCount[rd[r].roomtype ]+=1 else: rtCount[rd[r].roomtype] = 1 SoneRoom = [s for s in S if rtCount[sd[s].roomtype] == 1 ]
RSS = [(r,s1,s2) for r in R for s1 in SoneRoom for s2 in SoneRoom if s1 < s2 if sd[s1].roomtype == sd[s2].roomtype] for (r,s1,s2) in RSS: model.Add( y[s1,s2] == 1 ) for (p,s1,s2) in PSS: model.Add( y[s1,s2] == 1 ) for (g,c) in GC: model.Add(sum(x[g,s] for s in S if sd[s].course_num == c ) == 1 ) for s in S: model.Add(sum(x[g,s] for g in G if (g,s) in W ) <= sd[s].cap) for (g,s1,s2) in GlabtieSS: model.Add(x[g,s2] <= x[g,s1]) for (g,s1,s2) in GSS: model.AddBoolOr([x[g,s1].Not(), x[g,s2].Not(), y[s1,s2]]) print(’Ready to Solve’) solver = cp_model.CpSolver() print(’Created Solver’) solver.parameters.search_branching = (cp_model.sat_parameters_pb2.SatParameters.PORTFOLIO_WITH_QUICK_RESTART_SEARCH) solver.parameters.linearization_level = 0 solver.parameters.max_time_in_seconds = time solver.parameters.num_search_workers = int(threads) solution_printer = cp_model.ObjectiveSolutionPrinter() status = solver.SolveWithSolutionCallback(model , solution_printer) print(’Finished Solving’) if status == cp_model.OPTIMAL: print(’found optimal’) print(’Total edges = %i’ % solver.ObjectiveValue()) if status == cp_model.INFEASIBLE: print(’Infeasible’) exit() if status == cp_model.FEASIBLE: print(’found feasible’) print(’Total edges = %i’ % solver.ObjectiveValue()) if status in (cp_model.OPTIMAL , cp_model.FEASIBLE): x_m = {} y_m = {} for (s,t) in SS: y_m[s,t] = solver.Value(y[s,t]) for (g,s) in W: x_m[g,s] = solver.Value(x[g,s]) print(’saving pickle file’) mytuple = (x_m ,y_m ,flist) pickle.dump(mytuple , open( "saveX.p", "wb")) (gr,mini1 ,mini2 ,mini3) = CreateMiniGroups(x_m ,G,W,S) return mytuple B Timetabling CP-SAT Program def timetable(x_m , y_m , flist ,threads ,timeblock ,h_mprev = None): print(’timetable’) (S,R,RT,C,P,G,L,D,T,Lunch ,sd,rd,pd,gd,catalog ,divSizeDict ,divDict) = flist Sorig = list(S)
SallLab = [s for s in Sorig if sd[s].isExtended if sd[s].periods > 1.5] SallLab.append(0)
Sreg = [s for s in Sorig if s not in SallLab] if Lunch != -1: T = [t for t in T if t != Lunch ]
Y = set([(s,d,t,r) for s in S for d in D for t in T for r in R if (sd[s].roomtype == rd[r].roomtype) ]) W = set([(g,s) for g in G for s in S if (sd[s].course_num in gd[g].course_num_list) ]) Q = [(p,s) for p in P for s in S if sd[s].course_num in pd[p].secNums ]
S3 = [s for s in S if sd[s].isExtended and sd[s].periods == 3] if Lunch != -1: T3 = [t for t in T if ((t+2 < Lunch) or ((t > Lunch) and t+2 <= max(T) )) ] else: T3 = [t for t in T if t+2 <= max(T) ]
Y3 = set([(s,d,t,r) for s in S3 for d in D for t in T3 for r in R if (sd[s].roomtype ==rd[r].roomtype) ]) Y3h = set([(s,d,t) for s in S3 for d in D for t in T3 ])
S4 = [s for s in S if sd[s].isExtended and sd[s].periods == 4] if Lunch != -1: T4 = [t for t in T if t+3 < Lunch ] else: T4 = [t for t in T if t+3 <= max(T) ]
Y4 = set([(s,d,t,r) for s in S4 for d in D for t in T4 for r in R if (sd[s].roomtype ==rd[r].roomtype) ]) Y4h = set([(s,d,t) for s in S4 for d in D for t in T4 ])
S2 = [s for s in S if sd[s].isExtended and sd[s].periods == 2] if Lunch != -1: T2 = [t for t in T if ((t+1 < Lunch) or ((t > Lunch) and t+1 <= max(T) )) ] else: T2 = [t for t in T if t+1 <= max(T) ] Y2 = set([(s,d,t,r) for s in S2 for d in D for t in T2 for r in R if (sd[s].roomtype ==rd[r].roomtype) ]) Y2h = set([(s,d,t) for s in S2 for d in D for t in T2 ])
PS = [(p,s) for p in P for s in S if s in pd[p].secNums] PDT = [(p,d,t) for p in P for d in D for t in T] GDT = [(g,d,t) for g in G for d in D for t in T]
PDTS = set([(p,d,t,s) for p in P for d in D for t in T for s in S if (p,s) in Q]) GDTS = set([(g,d,t,s) for g in G for d in D for t in T for s in S if ( ( (g,s) in W) )]) GC = [(g,c) for g in G for c in C if c in gd[g].course_num_list ] DTR = set([(d,t,r) for d in D for t in T for r in R]) print(’model started’) m = cp_model.CpModel() SDT = [(s,d,t) for s in S for d in D for t in T] numRoomInType = {} for r in R: rt = rd[r].roomtype if rt in numRoomInType: numRoomInType[rt]+=1 else: numRoomInType[rt]=1 RT = list(numRoomInType.keys()) SS = [(s,t) for s in S for t in S if s < t if y_m[s,t] > 0.5] print(’Num sections ’,len(S)) print(’Num edges ’, len(SS)) solver = cp_model.CpSolver() solver.parameters.num_search_workers = int(threads) solver.parameters.max_time_in_seconds = timeblock solution_printer = cp_model.ObjectiveSolutionPrinter() m = cp_model.CpModel() h = {(s,d,t): m.NewBoolVar(’h%i%i%i’ % (s,d,t) ) for (s,d,t) in SDT} if h_mprev != None: for (s,d,t) in SDT: m.AddHint(h[s,d,t],h_mprev[s,d,t]) for s in S: m.Add(sum(h[s,d,t] for d in D for t in T if (s,d,t) in SDT ) == sd[s].periods) fe4h = {(s,d,t): m.NewBoolVar(’fe4h%i%i%i’ % (s,d,t) ) for (s,d,t) in Y4h} for s in S4: m.Add(sum( fe4h[s,d,t] for d in D for t in T if (s,d,t) in Y4h) == 1 ) for (s,d,t) in Y4h: m.Add(h[s,d,t] + h[s,d,t+1] + h[s,d,t+2] + h[s,d,t+3] >= 4*fe4h[s,d,t] ) for (s,d,t) in Y4h: m.AddImplication(fe4h[s,d,t],h[s,d,t] ) m.AddImplication(fe4h[s,d,t],h[s,d,t+1] ) m.AddImplication(fe4h[s,d,t],h[s,d,t+2] ) m.AddImplication(fe4h[s,d,t],h[s,d,t+3] ) fe3h = {(s,d,t): m.NewBoolVar(’fe3h%i%i%i’ % (s,d,t)) for (s,d,t) in Y3h } for s in S3: m.Add(sum( fe3h[s,d,t] for d in D for t in T if (s,d,t) in Y3h) == 1 ) for (s,d,t) in Y3h: m.AddImplication(fe3h[s,d,t],h[s,d,t] ) m.AddImplication(fe3h[s,d,t],h[s,d,t+1] ) m.AddImplication(fe3h[s,d,t],h[s,d,t+2] ) fe2h = {(s,d,t): m.NewBoolVar(’fe2h%i%i%i’ % (s,d,t)) for (s,d,t) in Y2h } for s in S2: m.Add(sum( fe2h[s,d,t] for d in D for t in T if (s,d,t) in Y2h) == 1 ) for (s,d,t) in Y2h: m.AddImplication(fe2h[s,d,t],h[s,d,t] ) m.AddImplication(fe2h[s,d,t],h[s,d,t+1] ) t2times = {(s,d):m.NewBoolVar(’t2times%i%i’ % (s,d) ) for s in S for d in D } for s in S: for d in D: if sd[s].periods == 1 or not sd[s].isExtended: m.Add( sum( h[s,d,t] for t in T if (s,d,t) in SDT ) <= 1 + t2times[s,d]) troomh = {(d,t,rt):m.NewBoolVar(’troomh%i%i%s’ % (d,t,rt) ) for d in D for t in T forrt in RT} for d in D: for t in T: for rt in RT: m.Add(sum( h[s,d,t] for s in S if sd[s].roomtype == rt) <= numRoomInType[rt] + 2*troomh[d,t,rt]) SS = [(s,t) for s in S for t in S if s < t if y_m[s,t] > 0.5] tconf = {(s1,s2,d,t):m.NewBoolVar(’tconf%i%i%i%i’ % (s1,s2,d,t) ) for (s1,s2) in SS ford in D for t in T } print(’3’) pof = {(p,d): m.NewBoolVar(’pof%i%i’ % (p,d)) for p in P for d in D} for p in P: m.Add( sum(pof[p,d] for d in D) <= len(D)-1 ) m.Add( pof[p,p%5] == 0 ) tpof = {p: m.NewBoolVar(’tpof%i’ % p) for p in P} for (p,s) in PS: for d in D: for t in T: m.Add(h[s,d,t] <= tpof[p]).OnlyEnforceIf(pof[p,d].Not()) comw = {s: 1 for s in S} comw[0] = 10 m.Minimize( 10*sum(t2times[s,d] for s in S for d in D) + sum(tpof[p] for p in P ) +sum(1000*comw[s1]*tconf[s1,s2,d,t] for (s1,s2) in SS for d in D for t in T) + 100*sum(troomh[d,t,rt] for d in D for t in T for rt in RT) ) startI=0 if h_mprev != None: startI = -1 tabu1 = None for i in range(startI ,2): if i == 0: limitTo = SallLab solver.parameters.max_time_in_seconds = timeblock if i == 1: limitTo = Sorig solver.parameters.max_time_in_seconds = timeblock for (s1,s2) in SS: for d in D: for t in T: if s1 in limitTo and s2 in limitTo: m.Add( h[s1,d,t] + h[s2,d,t] <= 1 + tconf[s1,s2,d,t] ) print(’Calling Solver’) status = solver.SolveWithSolutionCallback(m, solution_printer) if status == cp_model.INFEASIBLE: print(’Infeasible value of i is ’,i) return None if status in (cp_model.OPTIMAL , cp_model.FEASIBLE): print(’finished sections and common hour’) Temp104 = [(s1,s2,d,t) for (s1,s2) in SS for d in D for t in T if solver.Value(tconf[s1,s2,d,t]) > 0.5] if len(Temp104) > 0: tabu1 = [] for (s1,s2,d,t) in Temp104: print(’Conflict: ’,s1, s2, sd[s1].course_name , sd[s2].course_name , ’ time date’,d,t)
Temp105 = [g for g in G if (g,s1) in W if (g,s2) in W if x_m[g,s1] > 0.5 if x_m[g,s2] > 0.5] for g in Temp105: tabu1.append((g,s1)) tabu1.append((g,s2))
U1Ah = [(s,d,t) for (s,d,t) in SDT if s in limitTo if solver.Value(h[s,d,t]) > 0.5]
U1Bh = [(s,d,t) for (s,d,t) in SDT if s in limitTo if solver.Value(h[s,d,t]) < 0.5] for q in U1Ah: m.AddHint(h[q],1) for q in U1Bh: m.AddHint(h[q],0) if i==1: for q in U1Ah: m.Add(h[q]==1) for q in U1Bh: m.Add(h[q]==0) if status in (cp_model.OPTIMAL , cp_model.FEASIBLE): z = {(s,d,t,r): m.NewBoolVar(’z%i%i%i%i’ % (s,d,t,r) ) for (s,d,t,r) in Y} for (s,d,t) in SDT: m.Add( h[s,d,t] == sum(z[s,d,t,r] for r in R if (s,d,t,r) in Y) ) for s in S: m.Add(sum(z[s,d,t,r] for d in D for t in T for r in R if (s,d,t,r) in Y ) == sd[s].periods) fe4 = {(s,d,t,r): m.NewBoolVar(’fe4%i%i%i%i’ % (s,d,t,r) ) for (s,d,t,r) in Y4} for s in S4: m.Add(sum( fe4[s,d,t,r] for (d,t,r) in DTR if (s,d,t,r) in Y4) == 1 ) for (s,d,t,r) in Y4: m.Add(z[s,d,t,r] + z[s,d,t+1,r] + z[s,d,t+2,r] + z[s,d,t+3,r] >= 4*fe4[s,d,t,r] ) for (s,d,t,r) in Y4: m.AddImplication(fe4[s,d,t,r],z[s,d,t,r] ) m.AddImplication(fe4[s,d,t,r],z[s,d,t+1,r] ) m.AddImplication(fe4[s,d,t,r],z[s,d,t+2,r] ) m.AddImplication(fe4[s,d,t,r],z[s,d,t+3,r] ) fe3 = {(s,d,t,r): m.NewBoolVar(’fe3%i%i%i%i’ % (s,d,t,r)) for (s,d,t,r) in Y3 } for s in S3: m.Add(sum( fe3[s,d,t,r] for (d,t,r) in DTR if (s,d,t,r) in Y3) == 1 ) for (s,d,t,r) in Y3: m.AddImplication(fe3[s,d,t,r],z[s,d,t,r] ) m.AddImplication(fe3[s,d,t,r],z[s,d,t+1,r] ) m.AddImplication(fe3[s,d,t,r],z[s,d,t+2,r] ) fe2 = {(s,d,t,r): m.NewBoolVar(’fe2%i%i%i%i’ % (s,d,t,r)) for (s,d,t,r) in Y2 } for s in S2: m.Add(sum( fe2[s,d,t,r] for (d,t,r) in DTR if (s,d,t,r) in Y2) == 1 ) for (s,d,t,r) in Y2: m.AddImplication(fe2[s,d,t,r],z[s,d,t,r] ) m.AddImplication(fe2[s,d,t,r],z[s,d,t+1,r] ) troom = {(d,t,r):m.NewBoolVar(’troom%i%i%i’ % (d,t,r) ) for d in D for t in T for rin R} for d in D: for t in T: for r in R: m.Add(sum( z[s,d,t,r] for s in S if (s,d,t,r) in Y ) <= 1 + troom[d,t,r]) m.Minimize( 10*sum(t2times[s,d] for s in S for d in D) + 5*sum(tpof[p] for p in P ) +sum(1000* tconf[s1,s2,d,t] for (s1,s2) in SS for d in D for t in T) + 100*sum(troom[d,t,r] for d in D for t in T for r in R) ) print(’Calling Solver’) status = solver.SolveWithSolutionCallback(m, solution_printer) if status == cp_model.INFEASIBLE: print(’Infeasible Rooms’) return if status in (cp_model.OPTIMAL , cp_model.FEASIBLE): print(’reading z’) print(’reading z’) z_m = {} for q in Y: z_m[q] = solver.Value(z[q]) print(’computing w’) h_m = {(s,d,t): solver.Value(h[s,d,t]) for s in S for d in D for t in T } w_m = {} for (p,d,t) in PDT: w_m[p,d,t] = sum([h_m[s,d,t] for s in S if (p,s) in PS ] ) print(’computing u’) u_m = {(g,d,t,s) : 0 for (g,d,t,s) in GDTS} for (g,s) in W: if x_m[g,s] > 0.5: for d in D: for t in T: u_m[g,d,t,s] = sum( [ z_m[s,d,t,r] for r in R if (s,d,t,r) in Y ] ) savedSol = (flist ,x_m ,z_m ,w_m ,u_m ,GDTS) pickle.dump(savedSol , open("solX.p","wb") ) return (h_m ,tabu1 ,solver.ObjectiveValue()) else: print(’Did not solve’) References [Car00] Michael W Carter,
A comprehensive course timetabling and student scheduling system at theuniversity of waterloo , International Conference on the Practice and Theory of Automated18imetabling, Springer, 2000, pp. 64–82.[LD86] Gilbert Laporte and Sylvain Desroches,
The problem of assigning students to course sectionsin a large engineering school , Computers & operations research (1986), no. 4, 387–394.[MM10] Tomáš Müller and Keith Murray, Comprehensive approach to student sectioning , Annals ofOperations Research (2010), no. 1, 249–269.[MMR06] Keith Murray, Tomáš Müller, and Hana Rudová,
Modeling and solution of a complexuniversity course timetabling problem , International Conference on the Practice and Theoryof Automated Timetabling, Springer, 2006, pp. 189–209.[PF19] Laurent Perron and Vincent Furnon,
Or-tools , developers.google.com/optimization(2019).[Sch19] David Schindl,
Optimal student sectioning on mandatory courses with various sections num-bers , Annals of operations research (2019), no. 1, 209–221.[Sel88] Selim M. Selim,
Split vertices in vertex colouring and their application in developing a solutionto the faculty timetable problem , The Computer Journal31