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 000000000..0d382c0d1 Binary files /dev/null and b/gtsam_unstable/discrete/examples/Doodle2013.xls differ diff --git a/gtsam_unstable/discrete/examples/schedulingQuals12.cpp b/gtsam_unstable/discrete/examples/schedulingQuals12.cpp index 66c5b9bfc..1cb61e942 100644 --- a/gtsam_unstable/discrete/examples/schedulingQuals12.cpp +++ b/gtsam_unstable/discrete/examples/schedulingQuals12.cpp @@ -255,8 +255,8 @@ void sampleSolutions() { /* ************************************************************************* */ int main() { - runLargeExample(); -// solveStaged(3); +// runLargeExample(); + solveStaged(3); // sampleSolutions(); return 0; } diff --git a/gtsam_unstable/discrete/examples/schedulingQuals13.cpp b/gtsam_unstable/discrete/examples/schedulingQuals13.cpp new file mode 100644 index 000000000..5548e4300 --- /dev/null +++ b/gtsam_unstable/discrete/examples/schedulingQuals13.cpp @@ -0,0 +1,292 @@ +/* + * 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 +#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; +} +/* ************************************************************************* */ +