| 
									
										
										
										
											2012-04-16 06:35:28 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * CSP.cpp | 
					
						
							|  |  |  |  * @brief Constraint Satisfaction Problem class | 
					
						
							|  |  |  |  * @date Feb 6, 2012 | 
					
						
							|  |  |  |  * @author Frank Dellaert | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-15 08:47:19 +08:00
										 |  |  | #include <gtsam_unstable/discrete/Domain.h>
 | 
					
						
							|  |  |  | #include <gtsam_unstable/discrete/CSP.h>
 | 
					
						
							| 
									
										
										
										
											2012-04-16 06:35:28 +08:00
										 |  |  | #include <gtsam/base/Testable.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-08 22:33:59 +08:00
										 |  |  | using namespace std; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-16 06:35:28 +08:00
										 |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   /// Find the best total assignment - can be expensive
 | 
					
						
							| 
									
										
										
										
											2019-10-20 13:15:20 +08:00
										 |  |  |   CSP::sharedValues CSP::optimalAssignment() const { | 
					
						
							|  |  |  |     DiscreteBayesNet::shared_ptr chordal = this->eliminateSequential(); | 
					
						
							|  |  |  |     sharedValues mpe = chordal->optimize(); | 
					
						
							|  |  |  |     return mpe; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /// Find the best total assignment - can be expensive
 | 
					
						
							|  |  |  |   CSP::sharedValues CSP::optimalAssignment(const Ordering& ordering) const { | 
					
						
							| 
									
										
										
										
											2013-10-12 01:48:44 +08:00
										 |  |  |     DiscreteBayesNet::shared_ptr chordal = this->eliminateSequential(ordering); | 
					
						
							| 
									
										
										
										
											2013-10-12 01:42:30 +08:00
										 |  |  |     sharedValues mpe = chordal->optimize(); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |     return mpe; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-04-16 06:35:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   void CSP::runArcConsistency(size_t cardinality, size_t nrIterations, bool print) const { | 
					
						
							|  |  |  |     // Create VariableIndex
 | 
					
						
							| 
									
										
										
										
											2013-10-12 01:42:30 +08:00
										 |  |  |     VariableIndex index(*this); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |     // index.print();
 | 
					
						
							| 
									
										
										
										
											2012-04-16 06:35:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |     size_t n = index.size(); | 
					
						
							| 
									
										
										
										
											2012-04-16 06:35:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |     // Initialize domains
 | 
					
						
							|  |  |  |     std::vector < Domain > domains; | 
					
						
							|  |  |  |     for (size_t j = 0; j < n; j++) | 
					
						
							|  |  |  |       domains.push_back(Domain(DiscreteKey(j,cardinality))); | 
					
						
							| 
									
										
										
										
											2012-04-16 06:35:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |     // Create array of flags indicating a domain changed or not
 | 
					
						
							|  |  |  |     std::vector<bool> changed(n); | 
					
						
							| 
									
										
										
										
											2012-04-16 06:35:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |     // iterate nrIterations over entire grid
 | 
					
						
							|  |  |  |     for (size_t it = 0; it < nrIterations; it++) { | 
					
						
							|  |  |  |       bool anyChange = false; | 
					
						
							|  |  |  |       // iterate over all cells
 | 
					
						
							|  |  |  |       for (size_t v = 0; v < n; v++) { | 
					
						
							|  |  |  |         // keep track of which domains changed
 | 
					
						
							|  |  |  |         changed[v] = false; | 
					
						
							|  |  |  |         // loop over all factors/constraints for variable v
 | 
					
						
							| 
									
										
										
										
											2019-06-01 01:42:32 +08:00
										 |  |  |         const FactorIndices& factors = index[v]; | 
					
						
							| 
									
										
										
										
											2016-05-21 11:41:41 +08:00
										 |  |  |         for(size_t f: factors) { | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |           // if not already a singleton
 | 
					
						
							|  |  |  |           if (!domains[v].isSingleton()) { | 
					
						
							|  |  |  |             // get the constraint and call its ensureArcConsistency method
 | 
					
						
							|  |  |  |             Constraint::shared_ptr constraint = boost::dynamic_pointer_cast<Constraint>((*this)[f]); | 
					
						
							|  |  |  |             if (!constraint) throw runtime_error("CSP:runArcConsistency: non-constraint factor"); | 
					
						
							|  |  |  |             changed[v] = constraint->ensureArcConsistency(v,domains) || changed[v]; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } // f
 | 
					
						
							|  |  |  |         if (changed[v]) anyChange = true; | 
					
						
							|  |  |  |       } // v
 | 
					
						
							|  |  |  |       if (!anyChange) break; | 
					
						
							|  |  |  |       // TODO: Sudoku specific hack
 | 
					
						
							|  |  |  |       if (print) { | 
					
						
							|  |  |  |         if (cardinality == 9 && n == 81) { | 
					
						
							|  |  |  |           for (size_t i = 0, v = 0; i < (size_t)std::sqrt((double)n); i++) { | 
					
						
							|  |  |  |             for (size_t j = 0; j < (size_t)std::sqrt((double)n); j++, v++) { | 
					
						
							|  |  |  |               if (changed[v]) cout << "*"; | 
					
						
							|  |  |  |               domains[v].print(); | 
					
						
							|  |  |  |               cout << "\t"; | 
					
						
							|  |  |  |             } // i
 | 
					
						
							|  |  |  |             cout << endl; | 
					
						
							|  |  |  |           } // j
 | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |           for (size_t v = 0; v < n; v++) { | 
					
						
							|  |  |  |             if (changed[v]) cout << "*"; | 
					
						
							|  |  |  |             domains[v].print(); | 
					
						
							|  |  |  |             cout << "\t"; | 
					
						
							|  |  |  |           } // v
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         cout << endl; | 
					
						
							|  |  |  |       } // print
 | 
					
						
							|  |  |  |     } // it
 | 
					
						
							| 
									
										
										
										
											2012-04-16 06:35:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifndef INPROGRESS
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |     // Now create new problem with all singleton variables removed
 | 
					
						
							|  |  |  |     // We do this by adding simplifying all factors using parial application
 | 
					
						
							|  |  |  |     // TODO: create a new ordering as we go, to ensure a connected graph
 | 
					
						
							|  |  |  |     // KeyOrdering ordering;
 | 
					
						
							|  |  |  |     // vector<Index> dkeys;
 | 
					
						
							| 
									
										
										
										
											2016-05-21 11:41:41 +08:00
										 |  |  |     for(const DiscreteFactor::shared_ptr& f: factors_) { | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |       Constraint::shared_ptr constraint = boost::dynamic_pointer_cast<Constraint>(f); | 
					
						
							|  |  |  |       if (!constraint) throw runtime_error("CSP:runArcConsistency: non-constraint factor"); | 
					
						
							|  |  |  |       Constraint::shared_ptr reduced = constraint->partiallyApply(domains); | 
					
						
							|  |  |  |       if (print) reduced->print(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-04-16 06:35:28 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-04-16 06:35:28 +08:00
										 |  |  | } // gtsam
 | 
					
						
							|  |  |  | 
 |