172 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C
		
	
	
		
		
			
		
	
	
			172 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C
		
	
	
|  | /*
 | ||
|  |  * Scheduler.h | ||
|  |  * @brief an example how inference can be used for scheduling qualifiers | ||
|  |  * @date Mar 26, 2011 | ||
|  |  * @author Frank Dellaert | ||
|  |  */ | ||
|  | 
 | ||
|  | #pragma once
 | ||
|  | 
 | ||
|  | #include <gtsam_unstable/discrete/CSP.h>
 | ||
|  | 
 | ||
|  | 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 Scheduler : public CSP { | ||
|  | 
 | ||
|  | 	private: | ||
|  | 
 | ||
|  | 		/** Internal data structure for students */ | ||
|  | 		struct Student { | ||
|  | 			std::string name_; | ||
|  | 			DiscreteKey key_; // key for student
 | ||
|  | 			std::vector<DiscreteKey> keys_; // key for areas
 | ||
|  | 			std::vector<std::string> areaName_; | ||
|  | 			std::vector<double> 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<Student> students_; | ||
|  | 
 | ||
|  | 		/** faculty identifiers */ | ||
|  | 		std::map<std::string, size_t> facultyIndex_; | ||
|  | 		std::vector<std::string> facultyName_, slotName_, areaName_; | ||
|  | 
 | ||
|  | 		/** area constraints */ | ||
|  | 		typedef std::map<std::string, std::vector<double> > FacultyInArea; | ||
|  | 		FacultyInArea facultyInArea_; | ||
|  | 
 | ||
|  | 		/** nrTimeSlots * nrFaculty availability constraints */ | ||
|  | 		std::string available_; | ||
|  | 
 | ||
|  | 		/** which slots are good */ | ||
|  | 		std::vector<double> 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) { | ||
|  | 		} | ||
|  | 
 | ||
|  | 		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<double>& slotsAvailable) { | ||
|  | 			slotsAvailable_ = slotsAvailable; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		void addArea(const std::string& facultyName, const std::string& areaName) { | ||
|  | 			areaName_.push_back(areaName); | ||
|  | 			std::vector<double>& 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<size_t> 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<size_t> slot = boost::none); | ||
|  | 
 | ||
|  | 		/** Main routine that builds factor graph */ | ||
|  | 		void buildGraph(size_t mutexBound = 7); | ||
|  | 
 | ||
|  | 		/** print */ | ||
|  | 		void print(const std::string& s = "Scheduler") const; | ||
|  | 
 | ||
|  | 		/** Print readable form of assignment */ | ||
|  | 		void printAssignment(sharedValues assignment) const; | ||
|  | 
 | ||
|  | 		/** Special print for single-student case */ | ||
|  | 		void printSpecial(sharedValues assignment) const; | ||
|  | 
 | ||
|  | 		/** Accumulate faculty stats */ | ||
|  | 		void accumulateStats(sharedValues assignment, | ||
|  | 				std::vector<size_t>& stats) const; | ||
|  | 
 | ||
|  | 		/** Eliminate, return a Bayes net */ | ||
|  | 		DiscreteBayesNet::shared_ptr eliminate() const; | ||
|  | 
 | ||
|  | 		/** Find the best total assignment - can be expensive */ | ||
|  | 		sharedValues optimalAssignment() const; | ||
|  | 
 | ||
|  | 		/** find the assignment of students to slots with most possible committees */ | ||
|  | 		sharedValues bestSchedule() const; | ||
|  | 
 | ||
|  | 		/** find the corresponding most desirable committee assignment */ | ||
|  | 		sharedValues bestAssignment(sharedValues bestSchedule) const; | ||
|  | 
 | ||
|  | 	}; // Scheduler
 | ||
|  | 
 | ||
|  | } // gtsam
 | ||
|  | 
 | ||
|  | 
 |