| 1 | /* |
| 2 | * testScheduler.cpp |
| 3 | * @date March 25, 2011 |
| 4 | * @author Frank Dellaert |
| 5 | */ |
| 6 | |
| 7 | //#define ENABLE_TIMING |
| 8 | #include <CppUnitLite/TestHarness.h> |
| 9 | #include <gtsam/base/Testable.h> |
| 10 | #include <gtsam/base/timing.h> |
| 11 | #include <gtsam_unstable/discrete/Scheduler.h> |
| 12 | |
| 13 | |
| 14 | using namespace std; |
| 15 | using namespace gtsam; |
| 16 | |
| 17 | /* ************************************************************************* */ |
| 18 | // Create the expected graph of constraints |
| 19 | DiscreteFactorGraph createExpected() { |
| 20 | // Start building |
| 21 | size_t nrFaculty = 4, nrTimeSlots = 3; |
| 22 | |
| 23 | // variables assigning a time to a student: |
| 24 | // Akansel and Jake |
| 25 | DiscreteKey A(6, nrTimeSlots), J(7, nrTimeSlots); |
| 26 | |
| 27 | // variables assigning a faculty member to a student area |
| 28 | // Akansel:AI,ME,PC and Jake:HR,CT,AI |
| 29 | DiscreteKey A1(0, nrFaculty), J1(3, nrFaculty); |
| 30 | DiscreteKey A2(1, nrFaculty), J2(4, nrFaculty); |
| 31 | DiscreteKey A3(2, nrFaculty), J3(5, nrFaculty); |
| 32 | |
| 33 | CSP expected; |
| 34 | |
| 35 | // Area constraints |
| 36 | string faculty_in_A = "1 0 0 1" ; |
| 37 | string faculty_in_C = "0 0 1 0" ; |
| 38 | string faculty_in_H = "0 0 0 1" ; |
| 39 | string faculty_in_M = "0 1 0 0" ; |
| 40 | string faculty_in_P = "1 0 1 0" ; |
| 41 | string available = "1 1 1 0 1 1 1 1 0 1 1 1" ; |
| 42 | |
| 43 | // Akansel |
| 44 | expected.add(args&: A1, args&: faculty_in_A); // Area 1 |
| 45 | expected.add(args&: A1, args: "1 1 1 0" ); // Advisor |
| 46 | expected.add(args: A & A1, args&: available); |
| 47 | expected.add(args&: A2, args&: faculty_in_M); // Area 2 |
| 48 | expected.add(args&: A2, args: "1 1 1 0" ); // Advisor |
| 49 | expected.add(args: A & A2, args&: available); |
| 50 | expected.add(args&: A3, args&: faculty_in_P); // Area 3 |
| 51 | expected.add(args&: A3, args: "1 1 1 0" ); // Advisor |
| 52 | expected.add(args: A & A3, args&: available); |
| 53 | // Mutual exclusion for faculty |
| 54 | expected.addAllDiff(dkeys: A1 & A2 & A3); |
| 55 | |
| 56 | // Jake |
| 57 | expected.add(args&: J1, args&: faculty_in_H); // Area 1 |
| 58 | expected.add(args&: J1, args: "1 0 1 1" ); // Advisor |
| 59 | expected.add(args: J & J1, args&: available); |
| 60 | expected.add(args&: J2, args&: faculty_in_C); // Area 2 |
| 61 | expected.add(args&: J2, args: "1 0 1 1" ); // Advisor |
| 62 | expected.add(args: J & J2, args&: available); |
| 63 | expected.add(args&: J3, args&: faculty_in_A); // Area 3 |
| 64 | expected.add(args&: J3, args: "1 0 1 1" ); // Advisor |
| 65 | expected.add(args: J & J3, args&: available); |
| 66 | // Mutual exclusion for faculty |
| 67 | expected.addAllDiff(dkeys: J1 & J2 & J3); |
| 68 | |
| 69 | // Mutual exclusion for students |
| 70 | expected.addAllDiff(key1: A, key2: J); |
| 71 | |
| 72 | return expected; |
| 73 | } |
| 74 | |
| 75 | /* ************************************************************************* */ |
| 76 | TEST(schedulingExample, test) { |
| 77 | Scheduler s(2); |
| 78 | |
| 79 | // add faculty |
| 80 | s.addFaculty(facultyName: "Frank" ); |
| 81 | s.addFaculty(facultyName: "Harvey" ); |
| 82 | s.addFaculty(facultyName: "Magnus" ); |
| 83 | s.addFaculty(facultyName: "Andrea" ); |
| 84 | |
| 85 | // add time slots |
| 86 | s.addSlot(slotName: "Mon" ); |
| 87 | s.addSlot(slotName: "Wed" ); |
| 88 | s.addSlot(slotName: "Fri" ); |
| 89 | |
| 90 | // add areas |
| 91 | s.addArea(facultyName: "Frank" , areaName: "AI" ); |
| 92 | s.addArea(facultyName: "Frank" , areaName: "PC" ); |
| 93 | s.addArea(facultyName: "Harvey" , areaName: "ME" ); |
| 94 | s.addArea(facultyName: "Magnus" , areaName: "CT" ); |
| 95 | s.addArea(facultyName: "Magnus" , areaName: "PC" ); |
| 96 | s.addArea(facultyName: "Andrea" , areaName: "AI" ); |
| 97 | s.addArea(facultyName: "Andrea" , areaName: "HR" ); |
| 98 | |
| 99 | // add availability, nrTimeSlots * nrFaculty |
| 100 | string available = "1 1 1 0 1 1 1 1 0 1 1 1" ; |
| 101 | s.setAvailability(available); |
| 102 | |
| 103 | // add students |
| 104 | s.addStudent(studentName: "Akansel" , area1: "AI" , area2: "ME" , area3: "PC" , advisor: "Andrea" ); |
| 105 | s.addStudent(studentName: "Jake" , area1: "HR" , area2: "CT" , area3: "AI" , advisor: "Harvey" ); |
| 106 | |
| 107 | // BUILD THE GRAPH ! |
| 108 | s.buildGraph(); |
| 109 | // s.print(); |
| 110 | |
| 111 | // Check graph |
| 112 | DiscreteFactorGraph expected = createExpected(); |
| 113 | EXPECT(assert_equal(expected, (DiscreteFactorGraph)s)); |
| 114 | |
| 115 | // Do brute force product and output that to file |
| 116 | DecisionTreeFactor product = s.product()->toDecisionTreeFactor(); |
| 117 | // product.dot("scheduling", false); |
| 118 | |
| 119 | // Do exact inference |
| 120 | gttic(small); |
| 121 | auto MPE = s.optimize(); |
| 122 | gttoc(small); |
| 123 | |
| 124 | // print MPE, commented out as unit tests don't print |
| 125 | // s.printAssignment(MPE); |
| 126 | |
| 127 | // Commented out as does not work yet |
| 128 | // s.runArcConsistency(8,10,true); |
| 129 | |
| 130 | // find the assignment of students to slots with most possible committees |
| 131 | // Commented out as not implemented yet |
| 132 | // auto bestSchedule = s.bestSchedule(); |
| 133 | // GTSAM_PRINT(bestSchedule); |
| 134 | |
| 135 | // find the corresponding most desirable committee assignment |
| 136 | // Commented out as not implemented yet |
| 137 | // auto bestAssignment = s.bestAssignment(bestSchedule); |
| 138 | // GTSAM_PRINT(bestAssignment); |
| 139 | } |
| 140 | |
| 141 | /* ************************************************************************* */ |
| 142 | TEST(schedulingExample, smallFromFile) { |
| 143 | #if !defined(__QNX__) |
| 144 | string path(TOPSRCDIR "/gtsam_unstable/discrete/examples/" ); |
| 145 | #else |
| 146 | string path("" ); //Same Directory |
| 147 | #endif |
| 148 | Scheduler s(2, path + "small.csv" ); |
| 149 | |
| 150 | // add areas |
| 151 | s.addArea(facultyName: "Frank" , areaName: "AI" ); |
| 152 | s.addArea(facultyName: "Frank" , areaName: "PC" ); |
| 153 | s.addArea(facultyName: "Harvey" , areaName: "ME" ); |
| 154 | s.addArea(facultyName: "Magnus" , areaName: "CT" ); |
| 155 | s.addArea(facultyName: "Magnus" , areaName: "PC" ); |
| 156 | s.addArea(facultyName: "Andrea" , areaName: "AI" ); |
| 157 | s.addArea(facultyName: "Andrea" , areaName: "HR" ); |
| 158 | |
| 159 | // add students |
| 160 | s.addStudent(studentName: "Akansel" , area1: "AI" , area2: "ME" , area3: "PC" , advisor: "Andrea" ); |
| 161 | s.addStudent(studentName: "Jake" , area1: "HR" , area2: "CT" , area3: "AI" , advisor: "Harvey" ); |
| 162 | // s.print(); |
| 163 | |
| 164 | // BUILD THE GRAPH ! |
| 165 | s.buildGraph(); |
| 166 | |
| 167 | // Check graph |
| 168 | DiscreteFactorGraph expected = createExpected(); |
| 169 | EXPECT(assert_equal(expected, (DiscreteFactorGraph)s)); |
| 170 | } |
| 171 | |
| 172 | /* ************************************************************************* */ |
| 173 | int main() { |
| 174 | TestResult tr; |
| 175 | return TestRegistry::runAllTests(result&: tr); |
| 176 | } |
| 177 | /* ************************************************************************* */ |
| 178 | |