From 458707ed45c61e39c79fa719d6a1e61b9585a2f7 Mon Sep 17 00:00:00 2001 From: Frank Dellaert Date: Tue, 19 Mar 2013 18:05:13 +0000 Subject: [PATCH] Small changes for Qualifier 2013 Scheduling --- gtsam/discrete/DiscreteConditional.cpp | 15 +- gtsam/discrete/DiscreteFactorGraph.cpp | 3 +- gtsam/inference/GenericSequentialSolver-inl.h | 1 + gtsam_unstable/discrete/CMakeLists.txt | 1 + gtsam_unstable/discrete/Scheduler.cpp | 14 +- .../discrete/examples/Doodle2013.csv | 1 + .../discrete/examples/Doodle2013.xls | Bin 0 -> 12800 bytes .../discrete/examples/schedulingQuals12.cpp | 4 +- .../discrete/examples/schedulingQuals13.cpp | 292 ++++++++++++++++++ 9 files changed, 310 insertions(+), 21 deletions(-) create mode 100644 gtsam_unstable/discrete/examples/Doodle2013.csv create mode 100644 gtsam_unstable/discrete/examples/Doodle2013.xls create mode 100644 gtsam_unstable/discrete/examples/schedulingQuals13.cpp diff --git a/gtsam/discrete/DiscreteConditional.cpp b/gtsam/discrete/DiscreteConditional.cpp index 2e03e5478..ebf8c0c04 100644 --- a/gtsam/discrete/DiscreteConditional.cpp +++ b/gtsam/discrete/DiscreteConditional.cpp @@ -46,9 +46,8 @@ namespace gtsam { const DecisionTreeFactor& marginal) : IndexConditional(joint.keys(), joint.size() - marginal.size()), Potentials( ISDEBUG("DiscreteConditional::COUNT") ? joint : joint / marginal) { -// assert(nrFrontals() == 1); - if (ISDEBUG("DiscreteConditional::DiscreteConditional")) cout - << (firstFrontalKey()) << endl; //TODO Print all keys + if (ISDEBUG("DiscreteConditional::DiscreteConditional")) + cout << (firstFrontalKey()) << endl; //TODO Print all keys } /* ******************************************************************************** */ @@ -88,16 +87,8 @@ namespace gtsam { /* ******************************************************************************** */ void DiscreteConditional::solveInPlace(Values& values) const { -// OLD -// assert(nrFrontals() == 1); -// Index j = (firstFrontalKey()); -// size_t mpe = solve(values); // Solve for variable -// values[j] = mpe; // store result in partial solution -// OLD + // TODO: Abhijit asks: is this really the fastest way? He thinks it is. - // TODO: is this really the fastest way? I think it is. - - //The following is to make make adjustment for nFrontals \neq 1 ADT pFS = choose(values); // P(F|S=parentsValues) // Initialize diff --git a/gtsam/discrete/DiscreteFactorGraph.cpp b/gtsam/discrete/DiscreteFactorGraph.cpp index d7e615606..5c4d815fb 100644 --- a/gtsam/discrete/DiscreteFactorGraph.cpp +++ b/gtsam/discrete/DiscreteFactorGraph.cpp @@ -100,9 +100,8 @@ namespace gtsam { // PRODUCT: multiply all factors gttic(product); DecisionTreeFactor product; - BOOST_FOREACH(const DiscreteFactor::shared_ptr& factor, factors){ + BOOST_FOREACH(const DiscreteFactor::shared_ptr& factor, factors) product = (*factor) * product; - } gttoc(product); diff --git a/gtsam/inference/GenericSequentialSolver-inl.h b/gtsam/inference/GenericSequentialSolver-inl.h index 8b7d386fe..9dfe64fdc 100644 --- a/gtsam/inference/GenericSequentialSolver-inl.h +++ b/gtsam/inference/GenericSequentialSolver-inl.h @@ -32,6 +32,7 @@ namespace gtsam { template GenericSequentialSolver::GenericSequentialSolver(const FactorGraph& factorGraph) { gttic(GenericSequentialSolver_constructor1); + assert(factorGraph.size()); factors_.reset(new FactorGraph(factorGraph)); structure_.reset(new VariableIndex(factorGraph)); eliminationTree_ = EliminationTree::Create(*factors_, *structure_); diff --git a/gtsam_unstable/discrete/CMakeLists.txt b/gtsam_unstable/discrete/CMakeLists.txt index e0196dca2..6f19c65ea 100644 --- a/gtsam_unstable/discrete/CMakeLists.txt +++ b/gtsam_unstable/discrete/CMakeLists.txt @@ -29,6 +29,7 @@ add_dependencies(check.unstable check.discrete_unstable) set(discrete_unstable_examples schedulingExample schedulingQuals12 +schedulingQuals13 ) if (GTSAM_BUILD_EXAMPLES) diff --git a/gtsam_unstable/discrete/Scheduler.cpp b/gtsam_unstable/discrete/Scheduler.cpp index ff092bf8d..cf0e6f199 100644 --- a/gtsam_unstable/discrete/Scheduler.cpp +++ b/gtsam_unstable/discrete/Scheduler.cpp @@ -112,6 +112,7 @@ namespace gtsam { if (!slot && !slotsAvailable_.empty()) { if (debug) cout << "Adding availability of slots" << endl; + assert(slotsAvailable_.size()==s.key_.second); CSP::add(s.key_, slotsAvailable_); } @@ -122,21 +123,24 @@ namespace gtsam { const string& areaName = s.areaName_[area]; if (debug) cout << "Area constraints " << areaName << endl; + assert(facultyInArea_[areaName].size()==areaKey.second); CSP::add(areaKey, facultyInArea_[areaName]); if (debug) cout << "Advisor constraint " << areaName << endl; + assert(s.advisor_.size()==areaKey.second); CSP::add(areaKey, s.advisor_); if (debug) cout << "Availability of faculty " << areaName << endl; if (slot) { // get all constraints then specialize to slot - DiscreteKey dummy(0, nrTimeSlots()); - Potentials::ADT p(dummy & areaKey, available_); - Potentials::ADT q = p.choose(0, *slot); + size_t dummyIndex = maxNrStudents_*3+maxNrStudents_; + DiscreteKey dummy(dummyIndex, nrTimeSlots()); + Potentials::ADT p(dummy & areaKey, available_); // available_ is Doodle string + Potentials::ADT q = p.choose(dummyIndex, *slot); DiscreteFactor::shared_ptr f(new DecisionTreeFactor(areaKey, q)); CSP::push_back(f); } else { - CSP::add(s.key_, areaKey, available_); + CSP::add(s.key_, areaKey, available_); // available_ is Doodle string } } @@ -233,7 +237,7 @@ namespace gtsam { Values::const_iterator it = assignment->begin(); for (size_t area = 0; area < 3; area++, it++) { size_t f = it->second; - cout << setw(12) << it->first << ": " << facultyName_[f] << endl; + cout << setw(12) << studentArea(0,area) << ": " << facultyName_[f] << endl; } cout << endl; } diff --git a/gtsam_unstable/discrete/examples/Doodle2013.csv b/gtsam_unstable/discrete/examples/Doodle2013.csv new file mode 100644 index 000000000..6eedfc887 --- /dev/null +++ b/gtsam_unstable/discrete/examples/Doodle2013.csv @@ -0,0 +1 @@ +,Ayanna Howard,Ron Arkin,Henrik Christensen,Panos Tsiotras,Patricio Vela,Magnus Egerstedt,Fumin Zhang,Charles Isbell,Karen Feigh,Jun Ueda,Frank Dellaert,Andrea Thomaz,Wayne Book,Harvey Lipkin,Charlie Kemp,Mike Stilman,Jeff Shamma Mon 9:00 AM - 10:30 AM,1,,1,1,1,1,,1,,,1,,,1,1,,1 Mon 10:30 AM - 12:00 PM,1,,1,1,1,,1,,,1,1,1,1,,1,1, Mon 12:00 PM - 1:30 PM,1,1,,,1,1,1,,,1,1,1,1,1,1,1,1 Mon 1:30 PM - 3:00 PM,1,1,,,1,1,1,1,,1,1,1,1,1,,1,1 Mon 3:00 PM - 4:30 PM,1,,1,1,1,,1,1,,1,1,1,1,1,,1,1 Tue 9:00 AM - 10:30 AM,1,,1,1,,1,,1,,,1,,,1,,,1 Tue 10:30 AM - 12:00 PM,1,,1,1,,1,1,1,,1,1,1,,1,,1, Tue 12:00 PM - 1:30 PM,1,1,1,1,,1,1,1,1,,1,1,,1,,, Tue 1:30 PM - 3:00 PM,,1,,1,,,1,,1,1,1,1,,1,,1, Tue 3:00 PM - 4:30 PM,,,1,1,,1,1,,,1,,1,,1,,, Wed 9:00 AM - 10:30 AM,,,1,1,1,1,,1,1,,1,,,1,1,1, Wed 10:30 AM - 12:00 PM,,,1,1,1,1,1,1,,1,1,1,,,1,, Wed 12:00 PM - 1:30 PM,1,,,1,1,1,,1,,1,1,,,1,1,, Wed 1:30 PM - 3:00 PM,,,1,,1,1,,1,,1,1,,,1,1,1, Wed 3:00 PM - 4:30 PM,,,1,1,1,1,1,1,,1,,,,,1,,1 Thu 9:00 AM - 10:30 AM,1,,1,1,1,,,,,,1,,,1,1,,1 Thu 10:30 AM - 12:00 PM,,,1,1,1,,1,,,1,1,1,,1,,1, Thu 12:00 PM - 1:30 PM,,1,1,1,,,1,,1,,1,1,,1,,, Thu 1:30 PM - 3:00 PM,,,1,1,,,1,,1,1,1,1,,1,,1, Thu 3:00 PM - 4:30 PM,1,,1,1,,,1,,,1,,1,,,,1, Fri 9:00 AM - 10:30 AM,1,,1,1,,,,1,,,1,,,1,,, Fri 10:30 AM - 12:00 PM,,,1,1,1,,1,1,,1,1,1,,,1,1, Fri 12:00 PM - 1:30 PM,1,,1,1,1,,1,,,1,1,,,1,1,1, Fri 1:30 PM - 3:00 PM,1,,1,1,,,,,,1,1,,,1,,1, Fri 3:00 PM - 4:30 PM,,,1,1,1,,,,,1,1,,,1,,, \ No newline at end of file diff --git a/gtsam_unstable/discrete/examples/Doodle2013.xls b/gtsam_unstable/discrete/examples/Doodle2013.xls new file mode 100644 index 0000000000000000000000000000000000000000..0d382c0d1ecd1fbdd37f15eaa105b188fa2ca43d GIT binary patch literal 12800 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 rF@kJw%eJd*2g){;Y@f(yy?k!UXOJw +#include +#include + +#include +#include +#include +#include +#include + +#include + +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 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 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->rbegin()); + 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& 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 schedulers; + vector samplers(NRSTUDENTS); + + // Given the time-slots, we can create NRSTUDENTS independent samplers + vector 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 stats(nrFaculty, 0); + vector samples; + for (size_t i = 0; i < NRSTUDENTS; i++) { + samples.push_back(sample(*samplers[i])); + 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; +} +/* ************************************************************************* */ +