/* * schedulingExample.cpp * @brief hard scheduling example * @date March 25, 2011 * @author Frank Dellaert */ #define ENABLE_TIMING #define ADD_NO_CACHING #define ADD_NO_PRUNING #include #include #include #include using namespace std; using namespace gtsam; size_t NRSTUDENTS = 9; bool NonZero(size_t i) { return i > 0; } /* ************************************************************************* */ void addStudent(Scheduler& s, size_t i) { switch (i) { case 0: s.addStudent("Pan, Yunpeng", "Controls", "Perception", "Mechanics", "Eric Johnson"); break; case 1: s.addStudent("Sawhney, Rahul", "Controls", "AI", "Perception", "Henrik Christensen"); break; case 2: s.addStudent("Akgun, Baris", "Controls", "AI", "HRI", "Andrea Thomaz"); break; case 3: s.addStudent("Jiang, Shu", "Controls", "AI", "Perception", "Ron Arkin"); break; case 4: s.addStudent("Grice, Phillip", "Controls", "Perception", "HRI", "Charlie Kemp"); break; case 5: s.addStudent("Huaman, Ana", "Controls", "AI", "Perception", "Mike Stilman"); break; case 6: s.addStudent("Levihn, Martin", "AI", "Autonomy", "Perception", "Mike Stilman"); break; case 7: s.addStudent("Nieto, Carlos", "AI", "Autonomy", "Perception", "Henrik Christensen"); break; case 8: s.addStudent("Robinette, Paul", "Controls", "AI", "HRI", "Ayanna Howard"); break; } } /* ************************************************************************* */ Scheduler largeExample(size_t nrStudents = NRSTUDENTS) { string path("../../../gtsam_unstable/discrete/examples/"); Scheduler s(nrStudents, path + "Doodle2012.csv"); s.addArea("Harvey Lipkin", "Mechanics"); s.addArea("Jun Ueda", "Mechanics"); s.addArea("Patricio Vela", "Controls"); s.addArea("Magnus Egerstedt", "Controls"); s.addArea("Jun Ueda", "Controls"); s.addArea("Panos Tsiotras", "Controls"); s.addArea("Fumin Zhang", "Controls"); s.addArea("Henrik Christensen", "Perception"); s.addArea("Aaron Bobick", "Perception"); s.addArea("Mike Stilman", "AI"); // s.addArea("Henrik Christensen", "AI"); s.addArea("Ayanna Howard", "AI"); s.addArea("Charles Isbell", "AI"); s.addArea("Tucker Balch", "AI"); s.addArea("Ayanna Howard", "Autonomy"); s.addArea("Charlie Kemp", "Autonomy"); s.addArea("Tucker Balch", "Autonomy"); s.addArea("Ron Arkin", "Autonomy"); s.addArea("Andrea Thomaz", "HRI"); s.addArea("Karen Feigh", "HRI"); s.addArea("Charlie Kemp", "HRI"); // add students for (size_t i = 0; i < nrStudents; i++) addStudent(s, i); return s; } /* ************************************************************************* */ void runLargeExample() { Scheduler scheduler = largeExample(); scheduler.print(); // BUILD THE GRAPH ! size_t addMutex = 3; // SETDEBUG("Scheduler::buildGraph", true); scheduler.buildGraph(addMutex); // Do brute force product and output that to file if (scheduler.nrStudents() == 1) { // otherwise too slow DecisionTreeFactor product = *std::dynamic_pointer_cast(scheduler.product()); product.dot("scheduling-large", DefaultKeyFormatter, false); } // Do exact inference // SETDEBUG("timing-verbose", true); SETDEBUG("DiscreteConditional::DiscreteConditional", true); #define SAMPLE #ifdef SAMPLE gttic(large); DiscreteBayesNet::shared_ptr chordal = scheduler.eliminate(); gttoc(large); tictoc_finishedIteration(); tictoc_print(); for (size_t i=0;i<100;i++) { auto assignment = chordal->sample(); vector stats(scheduler.nrFaculty()); scheduler.accumulateStats(assignment, stats); size_t max = *max_element(stats.begin(), stats.end()); size_t min = *min_element(stats.begin(), stats.end()); size_t nz = count_if(stats.begin(), stats.end(), NonZero); // cout << min << ", " << max << ", " << nz << endl; if (nz >= 13 && min >=1 && max <= 4) { cout << "======================================================\n"; scheduler.printAssignment(assignment); } } #else gttic(large); auto MPE = scheduler.optimize(); gttoc(large); tictoc_finishedIteration(); tictoc_print(); scheduler.printAssignment(MPE); #endif } /* ************************************************************************* */ // Solve a series of relaxed problems for maximum flexibility solution void solveStaged(size_t addMutex = 2) { // super-hack! just count... bool debug = false; SETDEBUG("DiscreteConditional::COUNT", true); SETDEBUG("DiscreteConditional::DiscreteConditional", debug); // progress // make a vector with slot availability, initially all 1 // Reads file to get count :-) vector slotsAvailable(largeExample(0).nrTimeSlots(), 1.0); // now, find optimal value for each student, using relaxed mutex constraints for (size_t s = 0; s < NRSTUDENTS; s++) { // add all students first time, then drop last one second time, etc... Scheduler scheduler = largeExample(NRSTUDENTS - s); //scheduler.print(str(boost::format("Scheduler %d") % (NRSTUDENTS-s))); // only allow slots not yet taken scheduler.setSlotsAvailable(slotsAvailable); // BUILD THE GRAPH ! scheduler.buildGraph(addMutex); // Do EXACT INFERENCE gttic_(eliminate); DiscreteBayesNet::shared_ptr chordal = scheduler.eliminate(); gttoc_(eliminate); // find root node DiscreteConditional::shared_ptr root = chordal->back(); if (debug) root->print(""/*scheduler.studentName(s)*/); // solve root node only size_t bestSlot = root->argmax(); // get corresponding count DiscreteKey dkey = scheduler.studentKey(NRSTUDENTS - 1 - s); DiscreteValues values; values[dkey.first] = bestSlot; size_t count = (*root)(values); // remove this slot from consideration slotsAvailable[bestSlot] = 0.0; cout << scheduler.studentName(NRSTUDENTS - 1 - s) << " = " << scheduler.slotName(bestSlot) << " (" << bestSlot << "), count = " << count << endl; } tictoc_print_(); } /* ************************************************************************* */ // Sample from solution found above and evaluate cost function DiscreteBayesNet::shared_ptr createSampler(size_t i, size_t slot, vector& schedulers) { Scheduler scheduler = largeExample(0); // todo: wrong nr students addStudent(scheduler, i); SETDEBUG("Scheduler::buildGraph", false); scheduler.addStudentSpecificConstraints(0, slot); DiscreteBayesNet::shared_ptr chordal = scheduler.eliminate(); schedulers.push_back(scheduler); return chordal; } void sampleSolutions() { vector schedulers; vector samplers(NRSTUDENTS); // Given the time-slots, we can create NRSTUDENTS independent samplers vector slots{3, 20, 2, 6, 5, 11, 1, 4}; // given slots for (size_t i = 0; i < NRSTUDENTS; i++) samplers[i] = createSampler(i, slots[i], schedulers); // now, sample schedules for (size_t n = 0; n < 500; n++) { vector stats(19, 0); vector samples; for (size_t i = 0; i < NRSTUDENTS; i++) { samples.push_back(samplers[i]->sample()); schedulers[i].accumulateStats(samples[i], stats); } size_t max = *max_element(stats.begin(), stats.end()); size_t min = *min_element(stats.begin(), stats.end()); size_t nz = count_if(stats.begin(), stats.end(), NonZero); if (nz >= 15 && max <= 2) { cout << "Sampled schedule " << (n + 1) << ", min = " << min << ", nz = " << nz << ", max = " << max << endl; for (size_t i = 0; i < NRSTUDENTS; i++) { cout << schedulers[i].studentName(0) << " : " << schedulers[i].slotName( slots[i]) << endl; schedulers[i].printSpecial(samples[i]); } } } } /* ************************************************************************* */ int main() { // runLargeExample(); solveStaged(3); // sampleSolutions(); return 0; } /* ************************************************************************* */