| 
									
										
										
										
											2012-04-16 06:35:28 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * CSP.cpp | 
					
						
							|  |  |  |  * @brief Constraint Satisfaction Problem class | 
					
						
							|  |  |  |  * @date Feb 6, 2012 | 
					
						
							|  |  |  |  * @author Frank Dellaert | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <gtsam/base/Testable.h>
 | 
					
						
							| 
									
										
										
										
											2022-01-10 00:42:46 +08:00
										 |  |  | #include <gtsam/discrete/DiscreteBayesNet.h>
 | 
					
						
							| 
									
										
										
										
											2021-11-18 23:54:00 +08:00
										 |  |  | #include <gtsam_unstable/discrete/CSP.h>
 | 
					
						
							|  |  |  | #include <gtsam_unstable/discrete/Domain.h>
 | 
					
						
							| 
									
										
										
										
											2012-04-16 06:35:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-08 22:33:59 +08:00
										 |  |  | using namespace std; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-16 06:35:28 +08:00
										 |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-21 04:52:12 +08:00
										 |  |  | bool CSP::runArcConsistency(const VariableIndex& index, | 
					
						
							|  |  |  |                             Domains* domains) const { | 
					
						
							|  |  |  |   bool changed = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // iterate over all variables in the index
 | 
					
						
							|  |  |  |   for (auto entry : index) { | 
					
						
							|  |  |  |     // Get the variable's key and associated factors:
 | 
					
						
							|  |  |  |     const Key key = entry.first; | 
					
						
							|  |  |  |     const FactorIndices& factors = entry.second; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // If this domain is already a singleton, we do nothing.
 | 
					
						
							|  |  |  |     if (domains->at(key).isSingleton()) continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Otherwise, loop over all factors/constraints for variable with given key.
 | 
					
						
							|  |  |  |     for (size_t f : factors) { | 
					
						
							|  |  |  |       // If this factor is a constraint, call its ensureArcConsistency method:
 | 
					
						
							| 
									
										
										
										
											2023-01-18 06:39:55 +08:00
										 |  |  |       auto constraint = std::dynamic_pointer_cast<Constraint>((*this)[f]); | 
					
						
							| 
									
										
										
										
											2021-11-21 04:52:12 +08:00
										 |  |  |       if (constraint) { | 
					
						
							|  |  |  |         changed = constraint->ensureArcConsistency(key, domains) || changed; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return changed; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TODO(dellaert): This is AC1, which is inefficient as any change will cause
 | 
					
						
							|  |  |  | // the algorithm to revisit *all* variables again. Implement AC3.
 | 
					
						
							|  |  |  | Domains CSP::runArcConsistency(size_t cardinality, size_t maxIterations) const { | 
					
						
							| 
									
										
										
										
											2021-11-18 23:54:00 +08:00
										 |  |  |   // Create VariableIndex
 | 
					
						
							|  |  |  |   VariableIndex index(*this); | 
					
						
							| 
									
										
										
										
											2012-04-16 06:35:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-18 23:54:00 +08:00
										 |  |  |   // Initialize domains
 | 
					
						
							| 
									
										
										
										
											2021-11-21 04:52:12 +08:00
										 |  |  |   Domains domains; | 
					
						
							|  |  |  |   for (auto entry : index) { | 
					
						
							|  |  |  |     const Key key = entry.first; | 
					
						
							|  |  |  |     domains.emplace(key, DiscreteKey(key, cardinality)); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-04-16 06:35:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-21 04:52:12 +08:00
										 |  |  |   // Iterate until convergence or not a single domain changed.
 | 
					
						
							|  |  |  |   for (size_t it = 0; it < maxIterations; it++) { | 
					
						
							|  |  |  |     bool changed = runArcConsistency(index, &domains); | 
					
						
							|  |  |  |     if (!changed) break; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return domains; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-04-16 06:35:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-21 04:52:12 +08:00
										 |  |  | CSP CSP::partiallyApply(const Domains& domains) const { | 
					
						
							|  |  |  |   // Create new problem with all singleton variables removed
 | 
					
						
							|  |  |  |   // We do this by adding simplifying all factors using partial application.
 | 
					
						
							| 
									
										
										
										
											2021-11-18 23:54:00 +08:00
										 |  |  |   // TODO: create a new ordering as we go, to ensure a connected graph
 | 
					
						
							|  |  |  |   // KeyOrdering ordering;
 | 
					
						
							|  |  |  |   // vector<Index> dkeys;
 | 
					
						
							| 
									
										
										
										
											2021-11-21 04:52:12 +08:00
										 |  |  |   CSP new_csp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Add tightened domains as new factors:
 | 
					
						
							|  |  |  |   for (auto key_domain : domains) { | 
					
						
							|  |  |  |     new_csp.emplace_shared<Domain>(key_domain.second); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Reduce all existing factors:
 | 
					
						
							| 
									
										
										
										
											2021-11-18 23:54:00 +08:00
										 |  |  |   for (const DiscreteFactor::shared_ptr& f : factors_) { | 
					
						
							| 
									
										
										
										
											2023-01-18 06:39:55 +08:00
										 |  |  |     auto constraint = std::dynamic_pointer_cast<Constraint>(f); | 
					
						
							| 
									
										
										
										
											2021-11-18 23:54:00 +08:00
										 |  |  |     if (!constraint) | 
					
						
							|  |  |  |       throw runtime_error("CSP:runArcConsistency: non-constraint factor"); | 
					
						
							|  |  |  |     Constraint::shared_ptr reduced = constraint->partiallyApply(domains); | 
					
						
							| 
									
										
										
										
											2021-11-21 04:52:12 +08:00
										 |  |  |     if (reduced->size() > 1) { | 
					
						
							|  |  |  |       new_csp.push_back(reduced); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2021-11-21 04:52:12 +08:00
										 |  |  |   return new_csp; | 
					
						
							| 
									
										
										
										
											2021-11-18 23:54:00 +08:00
										 |  |  | } | 
					
						
							|  |  |  | }  // namespace gtsam
 |