// 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<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 // chordal->back()->print("back: "); // chordal->front()->print("front: "); // exit(0); DiscreteConditional::shared_ptr root = chordal->back(); 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; size_t 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_(); }
/* ************************************************************************* */ void accomodateStudent() { // super-hack! just count... bool debug = false; // SETDEBUG("DiscreteConditional::COUNT",true); SETDEBUG("DiscreteConditional::DiscreteConditional", debug); // progress Scheduler scheduler = largeExample(0); // scheduler.addStudent("Victor E", "Autonomy", "HRI", "AI", // "Henrik Christensen"); scheduler.addStudent("Carlos N", "Perception", "AI", "Autonomy", "Henrik Christensen"); scheduler.print("scheduler"); // rule out all occupied slots vector<size_t> slots; slots += 16, 17, 11, 2, 0, 5, 9, 14; vector<double> slotsAvailable(scheduler.nrTimeSlots(), 1.0); BOOST_FOREACH(size_t s, slots) slotsAvailable[s] = 0; scheduler.setSlotsAvailable(slotsAvailable); // BUILD THE GRAPH ! scheduler.buildGraph(1); // Do EXACT INFERENCE DiscreteBayesNet::shared_ptr chordal = scheduler.eliminate(); // find root node DiscreteConditional::shared_ptr root = chordal->back(); if (debug) root->print(""/*scheduler.studentName(s)*/); // GTSAM_PRINT(*chordal); // solve root node only Scheduler::Values values; size_t bestSlot = root->solve(values); // get corresponding count DiscreteKey dkey = scheduler.studentKey(0); values[dkey.first] = bestSlot; size_t count = (*root)(values); cout << boost::format("%s = %d (%d), count = %d") % scheduler.studentName(0) % scheduler.slotName(bestSlot) % bestSlot % count << endl; // sample schedules for (size_t n = 0; n < 10; n++) { Scheduler::sharedValues sample0 = chordal->sample(); scheduler.printAssignment(sample0); } }
/** Find the best total assignment - can be expensive */ Scheduler::sharedValues Scheduler::optimalAssignment() const { DiscreteBayesNet::shared_ptr chordal = eliminate(); if (ISDEBUG("Scheduler::optimalAssignment")) { DiscreteBayesNet::const_iterator it = chordal->end()-1; const Student & student = students_.front(); cout << endl; (*it)->print(student.name_); } gttic(my_optimize); sharedValues mpe = chordal->optimize(); gttoc(my_optimize); return mpe; }
/* ************************************************************************* */ 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 = chordal->sample(); 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 }
/* ************************************************************************* */ TEST(DiscreteBayesNet, Asia) { DiscreteBayesNet asia; // DiscreteKey A("Asia"), S("Smoking"), T("Tuberculosis"), L("LungCancer"), B( // "Bronchitis"), E("Either"), X("XRay"), D("Dyspnoea"); DiscreteKey A(0,2), S(4,2), T(3,2), L(6,2), B(7,2), E(5,2), X(2,2), D(1,2); // TODO: make a version that doesn't use the parser asia.add(A % "99/1"); asia.add(S % "50/50"); asia.add(T | A = "99/1 95/5"); asia.add(L | S = "99/1 90/10"); asia.add(B | S = "70/30 40/60"); asia.add((E | T, L) = "F T T T"); asia.add(X | E = "95/5 2/98"); // next lines are same as asia.add((D | E, B) = "9/1 2/8 3/7 1/9"); DiscreteConditional::shared_ptr actual = boost::make_shared<DiscreteConditional>((D | E, B) = "9/1 2/8 3/7 1/9"); asia.push_back(actual); // GTSAM_PRINT(asia); // Convert to factor graph DiscreteFactorGraph fg(asia); // GTSAM_PRINT(fg); LONGS_EQUAL(3,fg.back()->size()); Potentials::ADT expected(B & D & E, "0.9 0.3 0.1 0.7 0.2 0.1 0.8 0.9"); CHECK(assert_equal(expected,(Potentials::ADT)*actual)); // Create solver and eliminate Ordering ordering; ordering += Key(0),Key(1),Key(2),Key(3),Key(4),Key(5),Key(6),Key(7); DiscreteBayesNet::shared_ptr chordal = fg.eliminateSequential(ordering); // GTSAM_PRINT(*chordal); DiscreteConditional expected2(B % "11/9"); CHECK(assert_equal(expected2,*chordal->back())); // solve DiscreteFactor::sharedValues actualMPE = chordal->optimize(); DiscreteFactor::Values expectedMPE; insert(expectedMPE)(A.first, 0)(D.first, 0)(X.first, 0)(T.first, 0)(S.first, 0)(E.first, 0)(L.first, 0)(B.first, 0); EXPECT(assert_equal(expectedMPE, *actualMPE)); // add evidence, we were in Asia and we have Dispnoea fg.add(A, "0 1"); fg.add(D, "0 1"); // fg.product().dot("fg"); // solve again, now with evidence DiscreteBayesNet::shared_ptr chordal2 = fg.eliminateSequential(ordering); // GTSAM_PRINT(*chordal2); DiscreteFactor::sharedValues actualMPE2 = chordal2->optimize(); DiscreteFactor::Values expectedMPE2; insert(expectedMPE2)(A.first, 1)(D.first, 1)(X.first, 0)(T.first, 0)(S.first, 1)(E.first, 0)(L.first, 0)(B.first, 1); EXPECT(assert_equal(expectedMPE2, *actualMPE2)); // now sample from it DiscreteFactor::Values expectedSample; SETDEBUG("DiscreteConditional::sample", false); insert(expectedSample)(A.first, 1)(D.first, 1)(X.first, 0)(T.first, 0)( S.first, 1)(E.first, 0)(L.first, 0)(B.first, 1); DiscreteFactor::sharedValues actualSample = chordal2->sample(); EXPECT(assert_equal(expectedSample, *actualSample)); }
// 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<double> slotsAvailable(largeExample(0).nrTimeSlots(), 1.0); // now, find optimal value for each student, using relaxed mutex constraints for (size_t s = 0; s < 7; s++) { // add all students first time, then drop last one second time, etc... Scheduler scheduler = largeExample(7 - s); //scheduler.print(str(boost::format("Scheduler %d") % (7-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 Scheduler::Values values; size_t bestSlot = root->solve(values); // get corresponding count DiscreteKey dkey = scheduler.studentKey(6 - s); values[dkey.first] = bestSlot; size_t count = (*root)(values); // remove this slot from consideration slotsAvailable[bestSlot] = 0.0; cout << boost::format("%s = %d (%d), count = %d") % scheduler.studentName(6-s) % scheduler.slotName(bestSlot) % bestSlot % count << endl; } tictoc_print_(); // Solution with addMutex = 2: (20 secs) // TC = Wed 2 (9), count = 96375041778 // AC = Tue 2 (5), count = 4076088090 // SJ = Mon 1 (0), count = 29596704 // TK = Mon 3 (2), count = 755370 // JH = Wed 4 (11), count = 12000 // TH = Fri 2 (17), count = 220 // MN = Fri 1 (16), count = 5 // // Mutex does make a difference !! }