| 
									
										
										
										
											2013-03-20 02:05:13 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * 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 <gtsam_unstable/discrete/Scheduler.h>
 | 
					
						
							|  |  |  | #include <gtsam/base/debug.h>
 | 
					
						
							|  |  |  | #include <gtsam/base/timing.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <boost/assign/std/vector.hpp>
 | 
					
						
							|  |  |  | #include <boost/assign/std/map.hpp>
 | 
					
						
							|  |  |  | #include <boost/optional.hpp>
 | 
					
						
							|  |  |  | #include <boost/foreach.hpp>
 | 
					
						
							|  |  |  | #include <boost/format.hpp>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <algorithm>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace boost::assign; | 
					
						
							|  |  |  | using namespace std; | 
					
						
							|  |  |  | using namespace gtsam; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | size_t NRSTUDENTS = 12; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool NonZero(size_t i) { | 
					
						
							|  |  |  |   return i > 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | void addStudent(Scheduler& s, size_t i) { | 
					
						
							|  |  |  |   switch (i) { | 
					
						
							|  |  |  |   case 0: | 
					
						
							|  |  |  |     s.addStudent("Young, Carol", "Controls", "Autonomy", "Mechanics", "Fumin Zhang"); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case 1: | 
					
						
							|  |  |  |     s.addStudent("Erdogan, Can", "Controls", "AI", "Perception", "Mike Stilman"); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case 2: | 
					
						
							|  |  |  |     s.addStudent("Arslan, Oktay", "Controls", "AI", "Mechanics", "Panos Tsiotras"); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case 3: | 
					
						
							|  |  |  |     s.addStudent("Bhattacharjee, Tapomayukh", "Controls", "AI", "Mechanics", "Charlie Kemp"); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case 4: | 
					
						
							|  |  |  |     s.addStudent("Grey, Michael", "Controls", "AI", "Mechanics", "Wayne Book"); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case 5: | 
					
						
							|  |  |  |     s.addStudent("O'Flaherty, Rowland", "Controls", "AI", "Mechanics", "Magnus Egerstedt"); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case 6: | 
					
						
							|  |  |  |     s.addStudent("Pickem, Daniel", "Controls", "AI", "Mechanics", "Jeff Shamma"); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case 7: | 
					
						
							|  |  |  |     s.addStudent("Lee, Kimoon", "Controls", "Autonomy", "Mechanics", "Henrik Christensen"); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case 8: | 
					
						
							|  |  |  |     s.addStudent("Melim, Andrew Lyon", "Controls", "AI", "Perception", "Frank Dellaert"); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case 9: | 
					
						
							|  |  |  |     s.addStudent("Jensen, David", "Controls", "Autonomy", "HRI", "Andrea Thomaz"); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case 10: | 
					
						
							|  |  |  |     s.addStudent("Nisbett, Jared", "Controls", "Perception", "Mechanics", "Magnus Egerstedt"); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case 11: | 
					
						
							|  |  |  |     s.addStudent("Pan, Yunpeng", "Controls", "Perception", "Mechanics", "Wayne Book"); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  | //    case 12:
 | 
					
						
							|  |  |  | //    s.addStudent("Grice, Phillip", "Controls", "None", "None", "Wayne Book");
 | 
					
						
							|  |  |  | //    break;
 | 
					
						
							|  |  |  | //  case 13:
 | 
					
						
							|  |  |  | //    s.addStudent("Robinette, Paul", "Controls", "None", "None", "Ayanna Howard");
 | 
					
						
							|  |  |  | //    break;
 | 
					
						
							|  |  |  | //  case 14:
 | 
					
						
							|  |  |  | //    s.addStudent("Huaman, Ana", "Autonomy", "None", "None", "Mike Stilman");
 | 
					
						
							|  |  |  | //    break;
 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | Scheduler largeExample(size_t nrStudents = NRSTUDENTS, bool addStudents=true) { | 
					
						
							|  |  |  |   string path("../../../gtsam_unstable/discrete/examples/"); | 
					
						
							|  |  |  |   Scheduler s(nrStudents, path + "Doodle2013.csv"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s.addArea("Harvey Lipkin", "Mechanics"); | 
					
						
							|  |  |  |   s.addArea("Jun Ueda", "Mechanics"); | 
					
						
							|  |  |  |   s.addArea("Mike Stilman", "Mechanics"); | 
					
						
							|  |  |  | //  s.addArea("Frank Dellaert", "Mechanics");
 | 
					
						
							|  |  |  |   s.addArea("Wayne Book", "Mechanics"); | 
					
						
							|  |  |  | //  s.addArea("Charlie Kemp", "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("Ayanna Howard", "Controls"); | 
					
						
							|  |  |  |   s.addArea("Jeff Shamma", "Controls"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s.addArea("Frank Dellaert", "Perception"); | 
					
						
							|  |  |  |   s.addArea("Henrik Christensen", "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("Andrea Thomaz", "AI"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s.addArea("Ayanna Howard", "Autonomy"); | 
					
						
							|  |  |  |   s.addArea("Charlie Kemp", "Autonomy"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //  s.addArea("Andrea Thomaz", "HRI");
 | 
					
						
							|  |  |  |   s.addArea("Karen Feigh", "HRI"); | 
					
						
							|  |  |  | //  s.addArea("Charlie Kemp", "HRI");
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // add students
 | 
					
						
							|  |  |  |   if (addStudents) | 
					
						
							|  |  |  |     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 = scheduler.product(); | 
					
						
							|  |  |  |     product.dot("scheduling-large", 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++) { | 
					
						
							|  |  |  |     DiscreteFactor::sharedValues assignment = sample(*chordal); | 
					
						
							|  |  |  |     vector<size_t> 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); | 
					
						
							|  |  |  |   DiscreteFactor::sharedValues MPE = scheduler.optimalAssignment(); | 
					
						
							|  |  |  |   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) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bool debug = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // super-hack! just count...
 | 
					
						
							|  |  |  |   SETDEBUG("DiscreteConditional::COUNT", true); | 
					
						
							|  |  |  |   SETDEBUG("DiscreteConditional::DiscreteConditional", debug); // progress
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // make a vector with slot availability, initially all 1
 | 
					
						
							|  |  |  |   // Reads file to get count :-)
 | 
					
						
							|  |  |  |   vector<double> 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
 | 
					
						
							| 
									
										
										
										
											2013-10-12 05:55:31 +08:00
										 |  |  |     DiscreteConditional::shared_ptr root = chordal->back(); | 
					
						
							| 
									
										
										
										
											2013-03-20 02:05:13 +08:00
										 |  |  |     if (debug) | 
					
						
							|  |  |  |       root->print(""/*scheduler.studentName(s)*/); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // solve root node only
 | 
					
						
							|  |  |  |     Scheduler::Values values; | 
					
						
							|  |  |  |     size_t bestSlot = root->solve(values); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // get corresponding count
 | 
					
						
							|  |  |  |     DiscreteKey dkey = scheduler.studentKey(NRSTUDENTS - 1 - s); | 
					
						
							|  |  |  |     values[dkey.first] = bestSlot; | 
					
						
							|  |  |  |     double count = (*root)(values); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // remove this slot from consideration
 | 
					
						
							|  |  |  |     slotsAvailable[bestSlot] = 0.0; | 
					
						
							|  |  |  |     cout << boost::format("%s = %d (%d), count = %d") % scheduler.studentName(NRSTUDENTS-1-s) | 
					
						
							|  |  |  |         % scheduler.slotName(bestSlot) % bestSlot % count << endl; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   tictoc_print_(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | // Sample from solution found above and evaluate cost function
 | 
					
						
							|  |  |  | DiscreteBayesNet::shared_ptr createSampler(size_t i, | 
					
						
							|  |  |  |     size_t slot, vector<Scheduler>& schedulers) { | 
					
						
							|  |  |  |   Scheduler scheduler = largeExample(1,false); | 
					
						
							|  |  |  |   addStudent(scheduler, i); | 
					
						
							|  |  |  |   cout << " creating sampler for " << scheduler.studentName(0) << endl; | 
					
						
							|  |  |  |   SETDEBUG("Scheduler::buildGraph", false); | 
					
						
							|  |  |  | //  scheduler.print();
 | 
					
						
							|  |  |  |   scheduler.addStudentSpecificConstraints(0, slot); | 
					
						
							|  |  |  |   DiscreteBayesNet::shared_ptr chordal = scheduler.eliminate(); | 
					
						
							|  |  |  |   schedulers.push_back(scheduler); | 
					
						
							|  |  |  |   return chordal; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void sampleSolutions() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   size_t nrFaculty = 17; // Change to correct number !
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   vector<Scheduler> schedulers; | 
					
						
							|  |  |  |   vector<DiscreteBayesNet::shared_ptr> samplers(NRSTUDENTS); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Given the time-slots, we can create NRSTUDENTS independent samplers
 | 
					
						
							|  |  |  |   vector<size_t> slots; | 
					
						
							|  |  |  |   slots += 12,11,13, 21,16,1, 3,2,6, 7,22,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 < 10000; n++) { | 
					
						
							|  |  |  |     vector<size_t> stats(nrFaculty, 0); | 
					
						
							|  |  |  |     vector<Scheduler::sharedValues> samples; | 
					
						
							|  |  |  |     for (size_t i = 0; i < NRSTUDENTS; i++) { | 
					
						
							| 
									
										
										
										
											2013-10-12 03:01:12 +08:00
										 |  |  |       samples.push_back(samplers[i]->sample()); | 
					
						
							| 
									
										
										
										
											2013-03-20 02:05:13 +08:00
										 |  |  |       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 >= 16 && max <= 3) { | 
					
						
							|  |  |  |       cout << boost::format( | 
					
						
							|  |  |  |           "Sampled schedule %d, min = %d, nz = %d, max = %d\n") % (n + 1) % min | 
					
						
							|  |  |  |           % nz % max; | 
					
						
							|  |  |  |       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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | 
 |