/* * Scheduler.h * @brief an example how inference can be used for scheduling qualifiers * @date Mar 26, 2011 * @author Frank Dellaert */ #pragma once #include #include namespace gtsam { /** * Scheduler class * Creates one variable for each student, and three variables for each * of the student's areas, for a total of 4*nrStudents variables. * The "student" variable will determine when the student takes the qual. * The "area" variables determine which faculty are on his/her committee. */ class GTSAM_UNSTABLE_EXPORT Scheduler : public CSP { private: /** Internal data structure for students */ struct Student { std::string name_; DiscreteKey key_; // key for student std::vector keys_; // key for areas std::vector areaName_; std::vector advisor_; Student(size_t nrFaculty, size_t advisorIndex) : keys_(3), areaName_(3), advisor_(nrFaculty, 1.0) { advisor_[advisorIndex] = 0.0; } void print() const { using std::cout; cout << name_ << ": "; for (size_t area = 0; area < 3; area++) cout << areaName_[area] << " "; cout << std::endl; } }; /** Maximum number of students */ size_t maxNrStudents_; /** discrete keys, indexed by student and area index */ std::vector students_; /** faculty identifiers */ std::map facultyIndex_; std::vector facultyName_, slotName_, areaName_; /** area constraints */ typedef std::map > FacultyInArea; FacultyInArea facultyInArea_; /** nrTimeSlots * nrFaculty availability constraints */ std::string available_; /** which slots are good */ std::vector slotsAvailable_; public: /** * Constructor * We need to know the number of students in advance for ordering keys. * then add faculty, slots, areas, availability, students, in that order */ Scheduler(size_t maxNrStudents) : maxNrStudents_(maxNrStudents) {} /// Destructor virtual ~Scheduler() {} void addFaculty(const std::string& facultyName) { facultyIndex_[facultyName] = nrFaculty(); facultyName_.push_back(facultyName); } size_t nrFaculty() const { return facultyName_.size(); } /** boolean std::string of nrTimeSlots * nrFaculty */ void setAvailability(const std::string& available) { available_ = available; } void addSlot(const std::string& slotName) { slotName_.push_back(slotName); } size_t nrTimeSlots() const { return slotName_.size(); } const std::string& slotName(size_t s) const { return slotName_[s]; } /** slots available, boolean */ void setSlotsAvailable(const std::vector& slotsAvailable) { slotsAvailable_ = slotsAvailable; } void addArea(const std::string& facultyName, const std::string& areaName) { areaName_.push_back(areaName); std::vector& table = facultyInArea_[areaName]; // will create if needed if (table.empty()) table.resize(nrFaculty(), 0); table[facultyIndex_[facultyName]] = 1; } /** * Constructor that reads in faculty, slots, availibility. * Still need to add areas and students after this */ Scheduler(size_t maxNrStudents, const std::string& filename); /** get key for student and area, 0 is time slot itself */ const DiscreteKey& key(size_t s, boost::optional area = boost::none) const; /** addStudent has to be called after adding slots and faculty */ void addStudent(const std::string& studentName, const std::string& area1, const std::string& area2, const std::string& area3, const std::string& advisor); /// current number of students size_t nrStudents() const { return students_.size(); } const std::string& studentName(size_t i) const; const DiscreteKey& studentKey(size_t i) const; const std::string& studentArea(size_t i, size_t area) const; /** Add student-specific constraints to the graph */ void addStudentSpecificConstraints( size_t i, boost::optional slot = boost::none); /** Main routine that builds factor graph */ void buildGraph(size_t mutexBound = 7); /** print */ void print( const std::string& s = "Scheduler", const KeyFormatter& formatter = DefaultKeyFormatter) const override; /** Print readable form of assignment */ void printAssignment(const DiscreteValues& assignment) const; /** Special print for single-student case */ void printSpecial(const DiscreteValues& assignment) const; /** Accumulate faculty stats */ void accumulateStats(const DiscreteValues& assignment, std::vector& stats) const; /** Eliminate, return a Bayes net */ DiscreteBayesNet::shared_ptr eliminate() const; /** Find the best total assignment - can be expensive */ DiscreteValues optimalAssignment() const; /** find the assignment of students to slots with most possible committees */ DiscreteValues bestSchedule() const; /** find the corresponding most desirable committee assignment */ DiscreteValues bestAssignment(const DiscreteValues& bestSchedule) const; }; // Scheduler } // namespace gtsam